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章

猜你喜欢

转载自blog.csdn.net/sinat_38783046/article/details/82626617