1. 程式人生 > >vue2.X基礎知識五之非父子元件通訊

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會自動判斷是普通標籤還是元件。