1. 程式人生 > >Vue2.0筆記——組件3

Vue2.0筆記——組件3

Vue

非父子組件之間的通信

非父子關系的兩個組件之間也需要通信。在簡單的場景下,可以使用一個空的 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