Vue-元件通訊
一、父子元件間-自定義事件
子元件用$emit()
來觸發事件,父元件用$on
來監聽子元件的事件。
//父元件程式碼
<my-component
@increase="handleGetTotal"
></my-component>
//父元件函式程式碼
handleGetTotal:function(total){
this.total=total
}
//子元件程式碼
<div>
<button @click="handleIncrease">+1</button>
</div>
//子元件函式程式碼
handleIncrease:function(){
this.counter++;
this.$emit('increase',this.counter);
}
子元件通過click事件修改自己的counter值,並將得到的counter通過自定義事件increase傳遞給父元件,作為handleGetTotal函式的引數,並賦值給app的total變數。
二、父子元件間-使用v-model
在自定義元件上使用v-model實現雙向繫結。$emit()的事件名是特殊的”input”。
//父元件
<my-component v-model="total" ></my-component>
<button @click="handleReduce">-1</button>
//父元件函式
handleReduce:function(){
this.total--;
}
//子元件
Vue.component('my-component',{
props:['value'],
template:'<input :value="value" @input="updateValue">',
methods:{
updateValue:function(event) {
this.$emit('input',event.target.value);
}
}
});
父元件通過v-model將total值傳入子元件,子元件通過props中的value接收total值並通過v-bind顯示在input元素中;子元件自定義input事件,將在input元素中輸入的值通過$emit()傳遞給父元件的total。
三、任意元件間-中央事件匯流排(bus)
任意元件(包括父子、兄弟、跨級)間的通訊推薦使用一個空的Vue例項作為中央事件匯流排(bus),也就是一箇中介。
//html
<div id="app">
{{message}}
<component-a></component-a>
</div>
//js
var bus=new Vue();//定義一個空Vue例項作為中央事件匯流排
Vue.component('component-a',{
template:'<button @click="handleEvent">傳遞事件</button>',
methods:{
handleEvent:function(){
bus.$emit('on-message','來自元件component-a的內容');
}
}
});
var app=new Vue({
el:'#app',
data:{
message:'hello init'
},
mounted:function(){
var _this=this;
//在例項初始化時,監聽來自bus例項的事件
bus.$on('on-message',function(msg){
_this.message=msg;
})
}
});
子元件通過$emit()
給bus空例項添加了一個on-message自定義事件,父元件通過bus.$on()
監聽這個on-message事件。
四、祖孫元件間-父鏈
在子元件中使用this.$parent
可以直接訪問該元件的父例項或元件,父元件也可以通過this.$children
訪問它所有的子元件,而且可以遞歸向上或向下無限訪問,直到根例項或最內層的元件。
//html
<div id="app">
{{message}}
<component-a></component-a>
</div>
//js
Vue.component('component-a',{
template:'<button @click="handleEvent">傳遞事件</button>',
methods:{
handleEvent:function(){
//訪問到父鏈後,可以做任何操作,比如直接修改資料
this.$parent.message='來自元件component-a的內容';
}
}
});
var app=new Vue({
el:'#app',
data:{
message:'hello init'
}
});
注意,在業務中子元件應儘量避免依賴父元件的資料,更不該主動修改它的資料,因為這樣使得父子元件緊耦合。父子元件最好還是通過props和$emit()
來通訊。
五、父子元件間-子元件索引
當子元件較多時,可以使用子元件索引的方法,即用特殊的屬性ref來為子元件指定一個索引名稱。
在父元件模板中,子元件標籤上使用ref指定一個名稱,並在父元件內通過this.$refs
來訪問指定名稱的子元件。
//html
<div id="app">
<div>{{msg}}</div>
<button @click="handleRef">通過ref獲取子元件例項</button>
<component-a ref="comA"></component-a>
</div>
//js
Vue.component('component-a',{
template:'<div>子元件</div>',
data:function(){
return{
message:'子元件內容'
}
}
});
var app=new Vue({
el:'#app',
data:{
msg:'hello init'
},
methods:{
handleRef:function(){
var msg=this.$refs.comA.message;
this.msg=msg;
}
}
});
注意,$refs
只在元件渲染完成後才填充,並且它是非響應式的。它僅僅作為一個直接訪問子元件的應急方案,應當避免在木板或計算屬性中使用它。
——閱讀《Vue.js實戰》第7章