組件中的關(guān)系可分為父子組件通信、兄弟組件通信和跨級(jí)組件通信。
一、自定義事件 ---- 子組件給父組件傳遞數(shù)據(jù)
我們用 props 來(lái)接收父組件傳遞給子組件的數(shù)據(jù),那么子組件如何給父組件傳遞數(shù)據(jù)呢?
JavaScript 的一種設(shè)計(jì)模式 一一 觀察者模式,包含 dispatchEvent 和 addEventListener 這兩個(gè)方法。Vue 組件也有與之類(lèi)似的一套模式,子組件用 $emit() 來(lái)觸發(fā)事件,父組件用 $on() 來(lái)監(jiān)聽(tīng)子組件的事件 。
-
v--on除了監(jiān)聽(tīng) DOM 事件外,還可以用于組件之間的自定義事件。
- 第一步:在子組件標(biāo)簽上自定義事件
- 第二步: 在子組件的方法中用
$emit()觸發(fā)事件,第一個(gè)參數(shù)是事件名,后面的參數(shù)是要傳遞的數(shù)據(jù)(可以有 n 個(gè)參數(shù))- 第三步:在父組件的
methods的自定義事件中用一個(gè)參數(shù)來(lái)接受
<div id="app">
您現(xiàn)在的銀行卡余額是:{{total}} 元
<son-component @change="handleTotal"></son-component> <!-- change為自定義事件 -->
</div>
<script>
var app = new Vue({
el: "#app",
data: {
total: 2000
},
// 需求: 通過(guò)加號(hào)按鈕和減號(hào)按鈕來(lái)給父組件傳遞數(shù)據(jù)
components: {
'son-component': {
template: '<div>\
<button @click="handleincrease">+1000</button>\
<button @click="handlereduce">-1000</button>\
</div>',
data: function(){
return {
count: 2000
}
},
methods: {
handleincrease: function(){
this.count = this.count + 1000
// 觸發(fā)change事件,并把 this.count 傳遞過(guò)去
this.$emit('change',this.count)
},
handlereduce: function(){
this.count = this.count - 1000
this.$emit('change',this.count)
}
},
}
},
methods: {
handleTotal: function(value){
// 此處的形參 value 就是傳遞過(guò)來(lái)的數(shù)據(jù) count
this.total = value
}
}
})
</script>
二、在組件中使用 v--model
-
v--model其實(shí)是一個(gè)語(yǔ)法糖,這背后其實(shí)做了兩個(gè)操作:
-
v--bind指令綁定一個(gè)value屬性 -
v--on指令給當(dāng)前元素綁定input事件
- 使用
v--model要做到:
- 接收一個(gè)
value屬性 - 在有新的
value時(shí)觸發(fā) input 事件
<div id="app">
您現(xiàn)在的銀行卡余額是:{{total}} 元
<son-component v-model="total"></son-component>
v-model 其實(shí)就是綁定了 input 事件, 當(dāng)觸發(fā) input 時(shí),<br>
input 事件就會(huì)自動(dòng)接收傳遞過(guò)來(lái)的參數(shù), 并賦值給已經(jīng)綁定的 total。
</div>
<script>
var app = new Vue({
el: "#app",
data: {
total: 2000
},
components: {
'son-component': {
template: '<div>\
<button @click="handleincrease">+1000</button>\
</div>',
data: function(){
return {
count: 2000
}
},
methods: {
handleincrease: function(){
this.count = this.count + 1000
this.$emit('input',this.count)
}
},
}
}
})
</script>
this.$emit('input',this.count) 這行代碼會(huì)觸發(fā)一個(gè) input 事件,后面的參數(shù)就是傳遞給 v--model 綁定的屬性 total 的值。
三、非父組件之間的通信
-
官網(wǎng)描述:官網(wǎng)描述
-
圖形實(shí)例:子組件 A 與子組件 B 之間的通信圖形實(shí)例
- 非父組件之間進(jìn)行通信時(shí)(如將 A 組件數(shù)據(jù)傳遞給 B 組件),首先需要在根組件中定義一個(gè)
bus中介,然后在 A 組件中觸發(fā)一個(gè)事件并將參數(shù)傳遞過(guò)去 ,B 組件在實(shí)例創(chuàng)建的時(shí)候就監(jiān)聽(tīng)這個(gè)事件,并接收傳遞進(jìn)來(lái)的參數(shù)。
<div id="app">
<my-acomponent></my-acomponent>
<my-bcomponent></my-bcomponent>
</div>
<script>
var app = new Vue({
el: "#app",
data: {
bus: new Vue()
},
components: {
'my-acomponent': {
template: '<button @click="handle">點(diǎn)擊我向B組件傳遞數(shù)據(jù)</button>',
data: function(){
return {
amessage: '我是來(lái)自組件 A 的內(nèi)容'
}
},
methods: {
handle: function(){
this.$root.bus.$emit('lala', this.amessage)
}
}
},
'my-bcomponent': {
template: '<div></div>',
created: function(){
// A組件在實(shí)例創(chuàng)建的時(shí)候就監(jiān)聽(tīng)事件---lala事件
this.$root.bus.$on('lala', function(value){
alert(value)
})
}
}
}
})
</script>
- 父鏈:
this.$parent
子組件訪問(wèn)父組件的內(nèi)容:
<div id="app">
<child-component></child-component> --- {{msg}}
</div>
<script>
var app = new Vue({
el: "#app",
data: {
msg: '數(shù)據(jù)未修改'
},
components: {
'child-component': {
template: '<button @click="setParentData">點(diǎn)擊修改父組件內(nèi)容</button>',
methods: {
setParentData: function(){
this.$parent.msg = "數(shù)據(jù)已經(jīng)修改了"
}
}
}
}
})
</script>
- 子鏈:
this.$refs
父組件訪問(wèn)子組件內(nèi)容,用this.$children會(huì)找到所有的子組件。Vue 提供了為子組件提供索引的方法,用ref來(lái)指定一個(gè)屬性名稱(chēng),即為其增加一個(gè)索引。
<div id="app">
<my-acomponent ref="a"></my-acomponent>
<button @click="getChildData">我是父組件的按鈕,我要拿到子組件內(nèi)容</button> --- {{fromChild}}
</div>
<script>
var app = new Vue({
el: "#app",
data: {
fromChild: '還未拿到'
},
methods: {
getChildData: function(){
this.fromChild = this.$refs.a.amessage
}
},
components: {
'my-acomponent': {
template: '<div></div>',
data: function(){
return {
amessage: '我是來(lái)自組件 A 的內(nèi)容'
}
}
}
}
})
</script>

