vue2.X基礎知識五之非父子元件通訊
在實際業務中,除了父子元件通訊外,還有很多非父子元件通訊的場景,非父子元件一般有兩種,兄弟元件和跨多級元件。
1、中央事件匯流排(bus)處理任何元件通訊
在vue2.x中推薦使用一個空的Vue例項作為中央事件匯流排(bus),也就是一箇中介。例如:
<div id="app"> {{ message }} <component-a></component-a> </div> <script> var bus = new 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: '' }, mounted: function () { var _this = this; //在例項化時,監聽來自bus例項的事件 bus.$on('on-message', function (msg) { _this.message = msg; }); } }); </script>
首先建立了一個名為bus的空Vue例項,裡面沒有任何內容;然後全域性定義了元件component-a;最後建立Vue例項app,在app初始化時,也就是在生命週期mounted鉤子函式裡監聽了來自bus的事件on-message,而在元件component-a中,點選按鈕會通過bus把事件on-message發出去,此時app就會接收來自bus的事件,進而在回撥函式裡完成自己的業務邏輯。
這種方式巧妙而輕量地實現了任何元件間的通訊,包括父子、兄弟、跨級;如果深入使用,可以擴充套件bus例項,給它新增data、methods、computed等選項。在獲取公共資訊時候非常有用,只需在初始化時讓bus獲取一次,任何時間、任何元件就可以從中直接使用了。
2、父鏈
在子元件中,使用this.$parent可以直接訪問該元件的父例項或元件,父元件也可以通過this.$children訪問它所有的子元件,而且可以遞歸向上或向下無限訪問,直到根例項或最內層的元件。
<div id="app"> {{ message }} <component-a></component-a> </div> <script> /*vue儘管允許這種操作,但是不推薦使用*/ 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: '' }, });
儘管Vue允許子元件直接訪問父元件,但在業務中,子元件應該儘可能地避免依賴父元件的資料,更不應該去主動修改它的資料。父子元件最好還是通過props和$emit來通訊。
3、子元件索引
當子元件較多時,通過this.$children來一一遍歷我們需要的一個元件例項是比較困難的,尤其是元件動態與渲染時,他們的序列不固定。Vue提供了子元件索引的方法,用特殊的屬性ref來為子元件指定一個索引名稱;例如:<div id="app">
<button @click="handleRef">通過ref獲取子元件例項</button>
<component-a ref="comA"></component-a>
</div>
<script>
Vue.component('component-a', {
template: '<div>子元件</div>',
data: function () {
return {
message: '子元件內容'
}
}
});
var app = new Vue({
el: "#app",
methods: {
handleRef: function () {
//通過$refs來訪問指定的例項
var msg = this.$refs.comA.message;
console.log(msg);
}
}
});
在父元件模板中,子元件標籤上使用ref指定一個名稱,並在父元件內通過this.$refs來訪問指定名稱的子元件。
$refs只在元件渲染完成後才填充,並且它是非響應式的。它僅僅作為一個直接訪問子元件的應急方案,應當避免在模板或計算屬性中使用$refs。Vue2.x中ref會自動判斷是普通標籤還是元件。