vue組件詳解(三)——組件通訊

組件之間通訊能夠用下圖表示:app

組件關係可分爲父子組件通訊、兄弟組件通訊、跨級組件通訊。函數

1、自定義事件this

當子組件須要向父組件傳遞數據時,就要用到自定義事件。spa

子組件用$emit ()來觸發事件,父組件用$on()來監昕子組件的事件。雙向綁定

父組件能夠直接在子組件的自定義標籤上使用v-on 來監昕子組件觸發的自定義事件,如:code

        <div id="app9">
            <p>總數:{{total}}</p>
            <my-component9 @add="getTotal" @cut="getTotal"></my-component9>
        </div>
Vue.component('my-component9',{
    template: '<div>' +
    '               <button @click="increase">+1</button>' +
    '               <button @click="reduce">-1</button>' +
            '</div>',
    data: function(){
        return {
            count: 0
        }
    },
    methods:{
        increase: function(){
            this.count++;
            this.$emit('add',this.count)  //廣播的事件名和數據
        },
        reduce: function(){
            this.count--;
            this.$emit('cut',this.count)  //廣播的事件名和數據
        }
    }
});

var app9 = new Vue({
    el: '#app9',
    data:{
        total: 0
    },
    methods:{
        getTotal: function(count){
            this.total = count;
        }
    }
});

 

2、使用v-modelcomponent

Vue2 .x 能夠在自定義組件上使用v-model 指令,直接看一個事例:blog

        <div id="app10">
            <p>總數:{{total}}</p>
            <my-component10 v-model="total"></my-component10>  //這個地方v-model實際是一個語法糖,能夠直接理解爲接收到廣播input裏面的數據(this.total=count)。
        </div>
Vue.component('my-component10',{
    template: '<div>' +
                '<button @click="increase">+1</button>' +
                '<button @click="reduce">-1</button>' +
              '</div>',
    data: function(){
        return {
            count: 0
        }
    },
    methods:{
        increase: function(){
            this.count++;
            this.$emit('input',this.count)  //注意這個地方,廣播的事件名稱爲特殊的input
        },
        reduce: function(){
            this.count--;
            this.$emit('input',this.count)  //注意這個地方,廣播的事件名稱爲特殊的input
        }
    }
});

var app10 = new Vue({
    el: '#app10',
    data:{
        total: 0
    }
});

 

 v-model 還能夠用來建立自定義的表單輸入組件, 進行數據雙向綁定,例如:遞歸

        <div id="app11">
            <p>總數:{{total}}</p>
            <my-component11 v-model="total"></my-component11>
            <button @click="reduce">-1</button>
        </div>
Vue.component('my-component11', {
    props: ['value'],  //使用v-model的表單組件時,父組件經過value來進行傳值
    template: '<input :value="value" @input="updateValue">',
    methods: {
        updateValue: function(event){
            this.$emit('input', event.target.value);
        }
    }
});

var app11 = new Vue({
   el: '#app11',
   data:{
      total: 0
    },
    methods:{
        reduce: function(){
            this.total--
        }
    }
});

 

父組件的total發生變化時,會經過傳遞value值,影響子組件input中的value值,而子組件改變本身input中的value值,又會廣播給父組件,影響父組件中的total值。索引

實現這樣一個具備雙向綁定的v -model 組件要知足下面兩個要求:

•接收一個value 屬性。
• 在有新的value 時觸發input 事件。

 

3、非父子組件通訊

在Vue . 2.x 中, 推薦使用一個空的Vue 實例做爲中央事件總線( bu s ),也就是一箇中介。

直接看一個事例:

        <div id="app12">
            <p>{{message}}</p>
            <my-component12></my-component12>
        </div>
var bus = new Vue();

Vue.component('my-component12',{
   template: '<button @click="updateMessage">傳遞事件信息</button>',
    methods: {
        updateMessage: function(){
            bus.$emit('updateMessage','更新個人組件信息');   //利用中介bus傳播事件
        }
    }
});

var app12 = new Vue({
   el: '#app12',
   data:{
        message: ''
    },
    mounted: function(){
        var _this = this;   //這一步賦值必須有
        bus.$on('updateMessage',function(data){     //利用中介bus接收事件
            _this.message = data;
        })
    }
});

在app 初始化時,也就是在生命週期mounted 鉤子函數裏監聽了來自bus 的事件updateMessage(mounted掛載這一步至關於在兩個組件直間提早安排了一箇中介,當兩個組件通訊時,就能夠經過該中介相互傳遞消息了) ,

而在組件my-component12中,點擊按鈕會經過bus 把事件updateMessage發出去,此時app 就會接收到來自bus 的事件,進而在回調裏完成本身的業務邏輯。

這種方法巧妙而輕量地實現了任何組件間的通訊,包括父子、兄弟、跨級,並且Vue 1.x 和Vue 2.x 都適用。

 

4、父鏈與子組件索引

除了中央事件總線bus 外,還有兩種方法能夠實現組件間通訊:父鏈和子組件索引。

在子組件中,使用this.$parent 能夠直接訪問該組件的父實例或組件,父組件也能夠經過this.$children 訪問它全部的子組件,並且能夠遞歸向上或向下無線訪問, 直到根實例或最內層的組件。

4.1父鏈

        <div id="app13">
            <p>{{message}}</p>
            <my-component13></my-component13>
        </div>
Vue.component('my-component13',{
    template: '<button @click="updateMessage">經過父鏈直接修改數據</button>',
    methods: {
        updateMessage: function(){
            this.$parent.message = '來自組件my-component13的內容'  //經過this.$parent直接修改父組件的內容
        }
    }
});

var app13 = new Vue({
    el: '#app13',
    data:{
        message: ''
    }
});

 儘管V ue 容許這樣操做,但在業務中, 子組件應該儘量地避免依賴父組件的數據,更不該該去主動修改它的數據,由於這樣使得父子組件緊藕合,理想狀況下,只有組件本身能修改它的狀態。


4.2 子組件索引

當子組件較多時, 經過this.$children 來一一遍歷出咱們須要的一個組件實例是比較困難的,尤爲是組件動態渲染時,它們的序列是不固定的。Vue 提供了子組件索引的方法,用特殊的屬性ref來爲子組件指定一個索引名稱。

        <div id="app14">
            <p>{{message}}</p>
            <my-component14 ref="com14"></my-component14>
            <button @click="handleRef">經過ref獲取子組件實例</button>
        </div>
Vue.component('my-component14',{
    template: '<div>子組件</div>',
    data: function(){
        return {
            message: '子組件內容'
        }
    }
});

var app14 = new Vue({
    el: '#app14',
    data:{
        message: ''
    },
    methods: {
        handleRef: function(){
             this.message = this.$refs.com14.message;   //經過$refs獲取子組件實例
        }
    }
});

 在父組件模板中,子組件標籤上使用ref 指定一個名稱,井在父組件內經過this.$refs 來訪問指定名稱的子組件。

$refs 只在組件渲染完成後才填充,而且它是非響應式的. 它僅僅做爲一個直接訪問子組件的應急方案,應當儘可能避免在模板或計算屬性中使用$refs。

相關文章
相關標籤/搜索