聲明組件
let myComponent = Vue.extend({
template : '#my',
// 此時的 #my 是id="my"的template標(biāo)簽
});
// 可以簡化為
let myComponent = {
template : '#my',
data(){
// 此處的data必須是一個函數(shù)
}
};
注冊組件(全局組件, 局部組件)
// 全局組件: 一次注冊在所有的vue實例中(都能夠使用
Vue.component('my-component',{
template : '#my-component',
data () {
// 此處的data必須是一個函數(shù)
},
});
// 局部組件: 只能在某一個vue實例中使用
const vm = new Vue({
'el' : '#app',
components : {
'my-component' : {
template : '#my',
data() {
// 此處的data必須是一個函數(shù)
}
},
}
});
注: 為了保證各個組件的相互獨立性,所有的組件中的data必須是一個函數(shù)
組件之間的通信
- 父組件 => 子組件: props
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue study</title>
<script src="../node_modules/vue/dist/vue.js"></script>
</head>
<body>
<!-- templates -->
<template id="my">
<div>
<p>這是本組件自己的數(shù)據(jù): {{selfData}}</p>
<p>這是父組件的數(shù)據(jù): {{msg}}</p>
</div>
</template>
<!-- /templates -->
<!-- 使用組件 -->
<div id="app">
<my-component :msg="message"></my-component>
</div>
<script>
// 1.聲明一個組件
let myComponent = Vue.extend({
template: '#my',
props: ["msg"],
// props 不僅僅可以是一個數(shù)組,也可以是一個對象
data() {
return {
selfData: "hello Vue",
};
},
});
/** props 支持的類型=========================
1. 簡單語法
Vue.component('props-demo-simple', {
props: ['size', 'myMessage']
})
2. 對象語法缩筛,提供校驗
Vue.component('props-demo-advanced', {
props: {
// 檢測類型
height: Number,
// 檢測類型 + 其他驗證
age: {
type: Number,
default: 0,
required: true,
validator: function (value) {
return value >= 0
}
}
}
});
==================================*/
// 2.在Vue實例中來注冊組件
const vm = new Vue({
el: '#app',
data: {
message: 'hello world',
},
components: {
// 注冊一個局部組件
'my-component': myComponent,
// 注: 此時必須使用 - 分割單詞,或者全部小寫,不能使用駝峰式寫法
}
});
</script>
<!--
父組件 => 子組件: 在子組件中使用父組件的數(shù)據(jù)
1. 聲明一個組件
2. 注冊組件(全局或者局部組件都可以通信)
3. 使用組件(my-component), 并在使用時綁定一個屬性 :msg
4. 在子組件中用 props 來獲取綁定的屬性 props : ["msg"],
5. 測試,看是否能夠成功傳遞值
-->
</body>
</html>
- 子組件 => 父組件: 發(fā)布訂閱
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue study</title>
<script src="./node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 使用組件 -->
<my-component :msg="message" @custom_event="changeData"></my-component>
</div>
<!-- templates -->
<template id="my">
<div>
<p>{{msg}}</p>
<p>{{selfData}}</p>
<!-- <button @click="$emit('custom_enevt','args')">點我改變父組件的數(shù)據(jù)</button> -->
<!-- 如果覺得這種行內(nèi)的觸發(fā)滿足不了復(fù)雜的邏輯需求,你也可以把這個觸發(fā)寫到這個組件的方法中 -->
<button @click="triggerParent(10)">點我改變父組件的數(shù)據(jù)</button>
</div>
</template>
<script>
// 聲明一個組件
let myComponent = Vue.extend({
template: '#my',
props: ["msg"],
data() {
return {
selfData: 'hello Vue',
};
},
methods : {
triggerParent(val){
// 觸發(fā)父組件并傳遞一個參數(shù),此時的val是click調(diào)用時傳遞的參數(shù)
this.$emit('custom_event', val);
},
},
});
const vm = new Vue({
el: '#app',
data: {
message: 'hello world',
},
methods: {
changeData (val) {
// 把message變成一個隨機數(shù)連接上子組件傳遞的參數(shù)
this.message = val + Math.ceil(Math.random()*100);
},
},
components: {
// 注冊一個局部組件
'my-component': myComponent,
}
});
</script>
<!--
由于vue為了保證各個組件的獨立性,所以將各個組件的數(shù)據(jù)流向做成那單向數(shù)據(jù)流,
而這樣,就只能父組件改變子組件的內(nèi)容,而不能子組件改變父組件的內(nèi)容
所以為了能夠在子組件中改變父組件的數(shù)據(jù),只有使用自定義事件系統(tǒng)
1. 聲明一個組件 let myComponent = Vue.extend({...});
2. 注冊一個組件(全局,局部都行)
3. 使用組件
3.1) 綁定一個屬性 :msg="message" 子組件可以用 props 來獲取綁定的屬性
3.2) 綁定一個自定義事件 @custom_event="changeData" 此時的custom_event是事件名稱,changeData是methods中的方法
3.3) 子類想改變父類的數(shù)據(jù),可以用$emit('事件名稱')來觸發(fā)父組件的事件,然后由父組件決定改變的規(guī)則,從而達到單向數(shù)據(jù)流的目的
3.4) 觸發(fā)父類自定義事件
3.4.1) 行內(nèi)觸發(fā)
<button @click="$emit('custom_enevt','args')">點我改變父組件的數(shù)據(jù)</button> 此時的args是參數(shù)
3.4.2) 使用方法觸發(fā)
<button @click="triggerParent(10)">點我改變父組件的數(shù)據(jù)</button>
methods : {
triggerParent(val){
// 觸發(fā)父組件并傳遞一個參數(shù),此時的val是click調(diào)用時傳遞的參數(shù)
this.$emit('custom_event', val);
},
}
-->
</body>
</html>
- 組件嵌套的情況
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue組件嵌套</title>
<script src="./node_modules/vue/dist/vue.js"></script>
<style>
.cmpt1, .cmpt2 {
color: #ffffff;
padding: 15px;
}
.cmpt1 {
background: #272822;
}
.cmpt2 {
background: #265a88;
}
</style>
</head>
<body>
<div id="app">
<my-component @custom_event="changeData" :msg="message"></my-component>
</div>
<!-- templates -->
<template id="my">
<div>
<one :msg="msg" :name="name"></one>
<two :msg="msg" @test_event="changeMess"></two>
</div>
</template>
<!--one-->
<template id="one">
<div class="cmpt1">
<p>這是組件1</p>
<p>這是二級傳遞: hello {{msg}}!!! </p>
<p>這是三級傳遞: what's your name? my name is {{name}}</p>
</div>
</template>
<!--two-->
<template id="two">
<div class="cmpt2">
<p>這是組件2</p>
<p> hello {{msg}} </p>
<p>
<button @click="changePrentData(10)">點我改變父組件數(shù)據(jù)</button>
</p>
</div>
</template>
<script>
// 聲明一個子組件
let one = Vue.extend({
template: '#one',
props: ["msg", "name"],
});
// 聲明一個子組件
let two = Vue.extend({
template: '#two',
props: ["msg"],
methods: {
changePrentData(val) {
let m = Math.ceil(Math.random() * val);
// this.$emit('custom_event', m);
this.$emit('test_event', m);
}
},
});
// 聲明一個父組件
let myComponent = Vue.extend({
template: '#my',
props: ["msg"],
methods: {
changeMess(val){
this.$emit('custom_event',val);
}
},
components: {
'one': one,
'two': two
},
data() {
return {
name: 'Tom',
};
}
});
const vm = new Vue({
el: '#app',
data: {
message: 'world',
},
methods: {
changeData(val) {
this.message = "這是改變后的message,喜歡嗎? " + val + " 是點擊是傳遞的參數(shù)";
}
},
components: {
// 注冊一個局部組件
'my-component': myComponent,
}
});
</script>
<!--
組件嵌套時,最底層的組件想要與最頂層的組件通信,必須一層一層向上傳遞
-->
</body>
</html>
- 實例 模態(tài)框
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>蒙版效果</title>
<style>
* {
margin: 0;
padding: 0;
}
html, body {
width: 100%;
height: 3000px;
/* 為了測試滾動 */
}
#alert-panel {
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
position: absolute;
top: 0;
left: 0;
/*display: none;*/
}
#alert-panel #login {
width: 500px;
height: 300px;
background: #000000;
position: fixed;
top: 50%;
left: 50%;
margin-left: -250px;
margin-top: -180px;
}
#close-alert-panel {
background: #000;
color: #ffffff;
border: none;
width: 30px;
height: 30px;
float: right;
}
#close-alert-panel:hover {
background: #f00;
}
</style>
<!--javascript-->
<script src="./node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 當(dāng)點擊button的時候,顯示模態(tài)框,在模態(tài)框中點擊關(guān)閉按鈕時,關(guān)閉模態(tài)框 -->
<button id="btn" @click="showDialog">點擊登陸</button>
<modal :is-hide-dialog="!isHide" @close="closeModal"></modal>
</div>
<template id="dialog">
<div id="alert-panel" v-show="isHideDialog">
<div id="login">
<button id="close-alert-panel" @click="$emit('close')">×</button>
</div>
</div>
</template>
<script>
// 聲明一個組件
let modal = Vue.extend({
template: '#dialog',
props: ["isHideDialog"],
});
const vm = new Vue({
el: '#app',
data: {
isHide: true,
},
methods: {
showDialog() {
this.isHide = false;
},
closeModal() {
this.isHide = true;
}
},
components: {
'modal': modal
}
});
</script>
</body>
</html>
- 父組件調(diào)用子組件的方法
注: 如果ref放在組件上,那么通過$refs拿到的不是組件的dom而是這個組件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue study</title>
<script src="./node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 注: 如果ref放在組件上,那么通過$refs拿到的不是組件的dom而是這個組件 -->
<load ref="load"></load>
</div>
<!--templates-->
<template id="load">
<div v-if="isShow">
<p>玩命加載中...</p>
</div>
</template>
<!-- JavaScript -->
<script>
let load = Vue.extend({
template: '#load',
data () {
return {
isShow: true,
}
},
methods: {
hide(){
this.isShow = false;
console.log("我被調(diào)用了,這個組件已經(jīng)被隱藏了");
}
},
});
const vm = new Vue({
el: '#app',
components: {
"load": load,
},
mounted () {
// 當(dāng)vm實例掛載的時候,就調(diào)用子組件的方法,隱藏加載組件
this.$refs.load.hide();
}
});
</script>
</body>
</html>
- 在子組件中加工父組件傳遞的值
默認(rèn)在子組件中不能修改父組件傳遞的值,如果非要
加工父組件傳遞過來的數(shù)據(jù),可以使用 computed 屬性或者 data()
來加工父組件傳遞的值,此種方式雖然能夠加工了父組件
傳遞的數(shù)據(jù),但是不會改變父組件的數(shù)據(jù),保證了各個組件的獨立性(單向數(shù)據(jù)流)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue study</title>
<script src="./node_modules/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<my-comp :name="message"></my-comp>
</div>
<!--templates-->
<template id="my">
<div>
<p>父組件原數(shù)據(jù): {{name}}</p>
<p>改變后的數(shù)據(jù): {{myName}}</p>
<p>改變后的數(shù)據(jù): {{myName2}}</p>
</div>
</template>
<!-- JavaScript -->
<script>
// make a component
let myComponent = Vue.extend({
template: '#my',
props: ["name"],
// 要求: 在子組件中,將父組件傳遞的值拼接一個隨機數(shù)
// 方式一:使用計算屬性來改變父組件傳遞的值
computed:{
myName(){
return this.name + Math.random();
}
},
// 方式二:使用data()方法來改變父組件傳遞的值(局部變量)
data(){
return {
"myName2" :this.name + Math.random(),
}
},
});
const vm = new Vue({
el: '#app',
data: {
message: 'hello world',
},
components: {
// register a local component
"my-comp": myComponent,
},
});
</script>
</body>
</html>