1. 程式人生 > >Vue-元件通訊

Vue-元件通訊

一、父子元件間-自定義事件
子元件用$emit()來觸發事件,父元件用$on來監聽子元件的事件。

//父元件程式碼
<my-component
    @increase="handleGetTotal" 
></my-component>
//父元件函式程式碼
handleGetTotal:function(total){
    this.total=total
}
//子元件程式碼
<div>
    <button @click="handleIncrease">+1</button>
</div>
//子元件函式程式碼
handleIncrease:function(){ this.counter++; this.$emit('increase',this.counter); }

子元件通過click事件修改自己的counter值,並將得到的counter通過自定義事件increase傳遞給父元件,作為handleGetTotal函式的引數,並賦值給app的total變數。


二、父子元件間-使用v-model
在自定義元件上使用v-model實現雙向繫結。$emit()的事件名是特殊的”input”。

//父元件
<my-component v-model="total"
></my-component> <button @click="handleReduce">-1</button> //父元件函式 handleReduce:function(){ this.total--; }
//子元件
Vue.component('my-component',{
    props:['value'],
    template:'<input :value="value" @input="updateValue">',
    methods:{
        updateValue:function(event)
{
this.$emit('input',event.target.value); } } });

父元件通過v-model將total值傳入子元件,子元件通過props中的value接收total值並通過v-bind顯示在input元素中;子元件自定義input事件,將在input元素中輸入的值通過$emit()傳遞給父元件的total。


三、任意元件間-中央事件匯流排(bus)
任意元件(包括父子、兄弟、跨級)間的通訊推薦使用一個空的Vue例項作為中央事件匯流排(bus),也就是一箇中介。

//html
<div id="app">
    {{message}}
    <component-a></component-a>
</div>
//js
var bus=new Vue();//定義一個空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:'hello init'
    },
    mounted:function(){
        var _this=this;
        //在例項初始化時,監聽來自bus例項的事件
        bus.$on('on-message',function(msg){
            _this.message=msg;
        })
    }
});

子元件通過$emit()給bus空例項添加了一個on-message自定義事件,父元件通過bus.$on()監聽這個on-message事件。

四、祖孫元件間-父鏈
在子元件中使用this.$parent 可以直接訪問該元件的父例項或元件,父元件也可以通過this.$children 訪問它所有的子元件,而且可以遞歸向上或向下無限訪問,直到根例項或最內層的元件。

//html
<div id="app">
    {{message}}
    <component-a></component-a>
</div>
//js
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:'hello init'
    }
});

注意,在業務中子元件應儘量避免依賴父元件的資料,更不該主動修改它的資料,因為這樣使得父子元件緊耦合。父子元件最好還是通過props和$emit() 來通訊。

五、父子元件間-子元件索引
當子元件較多時,可以使用子元件索引的方法,即用特殊的屬性ref來為子元件指定一個索引名稱。
在父元件模板中,子元件標籤上使用ref指定一個名稱,並在父元件內通過this.$refs 來訪問指定名稱的子元件。

//html
<div id="app">
    <div>{{msg}}</div>
    <button @click="handleRef">通過ref獲取子元件例項</button>
    <component-a ref="comA"></component-a>
</div>
//js
Vue.component('component-a',{
    template:'<div>子元件</div>',
    data:function(){
        return{
            message:'子元件內容'
        }
    }
});
var app=new Vue({
    el:'#app',
    data:{
        msg:'hello init'
    },
    methods:{
        handleRef:function(){
            var msg=this.$refs.comA.message;
            this.msg=msg;
        }
    }
});

注意,$refs 只在元件渲染完成後才填充,並且它是非響應式的。它僅僅作為一個直接訪問子元件的應急方案,應當避免在木板或計算屬性中使用它。

——閱讀《Vue.js實戰》第7章