Vue2.0筆記——組件3
非父子關系的兩個組件之間也需要通信。在簡單的場景下,可以使用一個空的 Vue 實例作為事件總線。
這句話呢是官網原話,我們看官網的說明和例子。其通信的方法還是,觸發與監聽事件的方式,與子向父組件傳遞數據為相同的元素。也就是$emit方法和$on方法。接下來我們具體看看這個例子。
示例:
//空的Vue實例 var emptyVm = new Vue(); var vm = new Vue({ el:‘#app‘, components:{ ‘xiao-x‘:xiao_x, ‘xiao-y‘:xiao_y, ‘xiao-z‘:xiao_z } }); var xiao_x={ template:‘<div><p>組件x:{{name}}</p><button @click="send">傳遞數據</button></div>‘, data:function(){ return { name:‘xiao‘, username:‘yao‘ } }, methods:{ send(){ emptyVm.$emit(‘xiao-x‘,this.name); } } } var xiao_y={ template:‘<div><p>組件y:{{age}}</p><button @click="send">傳遞數據</button></div>‘, data:function(){ return { age:18 } }, methods:{ send(){ emptyVm.$emit(‘xiao-y‘,this.age); } } } var xiao_z={ template:‘<p>組件z:{{name}},{{age}}</p>‘, data:function(){ return { name:‘‘, age:‘‘ } } } <div id="app"> <xiao-x></xiao-x> <xiao-y></xiao-y> <xiao-z></xiao-z> </div>
運行實例,我們已經把該準備的已經準備好了。
x和y的模板呢,因為不想寫那麽高的篇幅代碼,就是稍微擠一塊了,接下來就是點擊按鈕觸發,然後z裏監聽就好了。
但是需要註意:必須先監聽,再觸發,才能夠監聽到,不然當然是接收不到的。所以監聽一定是在觸發執行前的。
代碼:
//x組件的事件方法 methods:{ send(){ emptyVm.$emit(‘xiao-x‘,this.name); } } //y的事件方法 methods:{ send(){ emptyVm.$emit(‘xiao-y‘,this.age); } } //z,在掛載組件模板實例之後就進行監聽,所以需要用的生命周期鉤子函數 mounted(){//模板掛載之後執行 emptyVm.$on(‘xiao-x‘, function(name){ vm.$children[2].name=name; }); emptyVm.$on(‘xiao-y‘,age =>{ this.age=age; }); }
好了,如此如此這般這般,就好了。運行案例,單擊按鈕,可以顯示出來。
接下來,解釋一下這些代碼:
- 首先呢,三個組件拉出來單獨寫,沒問題吧,聲明一個變量,對象賦給它就行
- 然後就是模板問題,我單獨擠一塊了,代碼多的話還是單獨寫吧
- 按鈕單擊事件觸發這個這個這兩個事件,給它參數,另一邊寫上事件名,加上回調函數。
- 然後,你要想監聽必須是在觸發前吧,什麽時候最早,掛載之後唄,所以整個$on監聽,回調函數裏跟上實參,就好了。
說明兩個問題:
1.就是為什麽要空的Vue實例:
主要就是創建一個空的實例作為中轉站繼而能通過$emit和$on這兩個函數來實現,為什麽呢,因為,這兩個方法是,觸發當前實例/監聽當前實例
2.$on事件方法回調問題:
就例如第一個監聽name的,如果你直接this.name=name,你覺得會不會錯。之所以這麽寫肯定是有問題的,但是它不會報錯。只不過賦值賦錯了,打印一下這個this,通過data屬性在某個實例中的方法發現這個this是emptyVm的實例,因為回調函數裏的this是新的this,指向emptyVm。所以你需要得到z的組件實例才能復制,所以通過$children得到子實例才能賦值,當然這個$children可能是有問題的,因為官方說它是不保證順序的,我也不太清楚。
所以你需要使用的是第二種,箭頭的方式,它不會在函數中創建一個新的this。
箭頭函數的格式是:實參列表 =>{//操作內容}
slot內容分發
原意是,槽,插槽的意思。
有什麽用呢,我們先看一下下面的例子。
示例:
<div id="app">
<my-xiao></my-xiao>
</div>
<template id="xiao">
<div>
{{arr.join(‘ ‘)}}<br/>
</div>
</template>
components:{
‘my-xiao‘:{
template:‘#xiao‘,
data:function(){
return {
name:‘xiao‘,
arr:[‘what‘,‘are‘,‘you‘,‘doing‘]
}
}
}
}
這個例子看起來也沒怎麽樣,但是呢,你會發現<my-xiao>這個標簽內空空如也,是不是想加點文字,可是無論怎麽加,都會被模板替換掉的。
1.
這時,就是使用插槽的時候了,它使用<slot></slot>標簽來顯示,只需將它放在模板中任意為值即可,要註意的是,slot也是一個組件哦,內置的。
<div id="app">
<my-xiao>空空如也 —— 任然</my-xiao>
</div>
<template id="xiao">
<div>
{{arr.join(‘ ‘)}}<br/>
<slot></slot><!-- 代替標簽內的文字 -->
</div>
</template>
//或者,當內有內容時顯示默認的值
<template id="xiao">
<div>
{{arr.join(‘ ‘)}}<br/>
<slot>只有在沒有要分發的內容時才會顯示。</slot>
</div>
</template>
2.你更可以在<my-xiao>標簽中添加任意代碼,如常用的ul,li.同樣會顯示。
<my-xiao>
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
</my-xiao>
3.你可以通過<slot></slot>指定某個元素在模板的哪裏顯示
<my-xiao>
<ul slot="one">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
<p slot="QianSiXian">你襤褸我彩繪 並肩行過山與水</p>
</my-xiao>
<template id="xiao">
<div>
<slot name="QianSiXian"></slot>
{{arr.join(‘ ‘)}}<br/>
<slot name="one"></slot>
</div>
</template>
你可以為元素設置slot屬性,並隨意設置一個值,只需要在slot標簽中通過name指定名稱即可。
Vue2.0筆記——組件3