Vue 基础篇(一):Vue组件间通信

407 阅读2分钟

本博客主要是介绍各种情景下的Vue组件间的通信

一、父组件向子组件通信

1、使用props

使用props,父组件可以使用props向子组件传递数据。

<div id="demo1">
    <children-div-1 v-bind:parent-message="message"></children-div-1>
</div>

Vue.component("children-div-1",{
    props:["parentMessage"],
    template : `
        <div>
            <p>{{ parentMessage }}</p>
        </div>
    `
});
new Vue({
    el : "#demo1",
    data : {
        message : "这里是来自父组件的消息"
    }
});

2、使用$children(不推荐)

$children返回组件的一个子组件集合

<div id="demo2">
    <p @click="changeMessage">点击改变子组件的消息</p>
    <children-div-2></children-div-2>
</div>

var childrenDiv2 = {
    template : `
        <div>
            <p>{{ message }}</p>
        </div>
    `,
    data : function(){
        return {message : "这里是子组件消息"}
    }
}
new Vue({
    el : "#demo2",
    components : {
        "children-div-2" : childrenDiv2
    },
    methods : {
        changeMessage : function(){
            this.$children[0].message = "父组件改变了子组件的消息";
        }
    }
});

二、子组件向父组件通信

1、使用vue事件

父组件向子组件传递事件方法,子组件通过$emit触发事件,回调给父组件。

<div id="demo3">
    <children-div-3 v-on:change-message="changeMessage"></children-div-3>
    <p>{{ message }}</p>
</div>

Vue.component("children-div-3",{
    template : `
        <div>
            <p @click="$emit('change-message','子组件要求改变消息')">点击改变父组件的消息</p>
        </div>
    `
});
new Vue({
    el : "#demo3",
    data : {
        message : "这里是父组件的消息"
    },
    methods : {
        changeMessage : function(data){
            this.message = data;
        }
    }
});

2、使用$parent(不推荐)

$parent返回组件的父组件

<div id="demo4">
    <children-div-4></children-div-4>
    <p>{{ message }}</p>
</div>

Vue.component("children-div-4",{
    template : `
        <div>
            <p @click="changeMessage">点击改变父组件的消息</p>
        </div>
    `,
    methods : {
        changeMessage : function(){
            this.$parent.message = "子组件要求改变消息";
        }
    }
});
new Vue({
    el : "#demo4",
    data : {
        message : "这里是父组件的消息"
    }
});

三、多层级父子组件通信

1、使用inheritAttrs + $attrs + $listenerst

inheritAttrs:默认值为true,设置为false时,没有被子组件继承的父组件属性(子组件的属性定义在组件的props中),不会当做特性展示在子组件根元素上面。

默认情况下父作用域的不被认作props的特性绑定(attribute bindings)将会“回退”且作为普通的HTML特性应用在子组件的根元素上。  
当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。  
通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。
而通过 (同样是 2.4 新增的) 实例属性 $attrs 可以让这些特性生效,且可以通过 v-bind 显性的绑定到非根元素上。

$attrs:存放没有被子组件继承的的数据对象

包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外)。
当一个组件没有声明任何 props 时,这里会包含所有父作用域的绑定 (class 和 style 除外),
并且可以通过 v-bind=”$attrs” 传入内部组件——在创建更高层次的组件时非常有用。

$listeners:含了作用在这个组件上的所有监听器

包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。
它可以通过 v-on=”$listeners” 传入内部组件——在创建更高层次的组件时非常有用.

父组件中未被props(v-on)绑定的属性(事件) 可以在子组件中,通过 $attrs, $listeners 获取。

<div id="demo6">
    <p>{{ message }}</p>
    <!-- 向后代组件传递消息并且绑定时间监听 -->
    <children-div-6
        v-bind:son-message="sonMessage"
        v-bind:grandson-message="grandsonMessage"
        v-on:change="change"
    ></children-div-6>
</div>

var grandSonDiv = {
    props : ["grandsonMessage"],
    template : `
        <div>
            <p @click="$emit('change','这里是来自后代组件的消息')">{{ grandsonMessage }}</p>
        </div>
    `,
}
var childrenDiv ={
    props : ["sonMessage"],
    // inheritAttrs设置为false,子组件只获取props中定义属性所接送的消息,其余的都不继承,保存在$attrs中
    // $attrs 获取没有被子组件继承的数据对象,传递给后代组件
    // v-on="$listeners" 包含了所有的监听器,所以将后代组件触发的事件通报给父组件
    template : `
        <div>
            <p>{{ sonMessage }}</p>
            <grandson-div v-bind=$attrs v-on="$listeners"></grandson-div>
        </div>
    `,
    inheritAttrs : false,
    components : {
        "grandson-div" : grandSonDiv
    }
};
new Vue({
    el : "#demo6",
    data : {
        message : "这里是父组件自己的消息",
        sonMessage : "这是给子组件的消息",
        grandsonMessage : "这是给后代组件的消息"
    },
    components : {
        "children-div-6" : childrenDiv
    },
    methods : {
        change : function(val){
            this.message = val;
        }
    }
})

四、任意两个组件之间的数据传递

1、使用VueX

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,

Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。

2、创建一个事件中心进行全局传递与接受事件

创建一个事件中心Hub,相当于中转站,可以用它来进行全局传递事件和接收事件。

<div id="demo5">
    <one-div></one-div>
    <other-div></other-div>
</div>

var Hub = new Vue(); //创建事件中心,注意Hub要放在全局

Vue.component("one-div",{
    template : `
        <div>
            <p @click="sendMessage">向另外一个组件发送消息</p>
        </div>
    `,
    methods : {
        sendMessage : function(){
            Hub.$emit("change","我是来自另外一个组件的消息");
        }
    }
})
Vue.component("other-div",{
    template : `
        <div>
            <p>{{ message }}</p>
        </div>
    `,
    data : function(){
        return {message : "这里显示的我自己组件的消息"}
    },
    created(){
        Hub.$on("change",(val) =>{
            this.message = val;
        })
    }
})
new Vue({
    el : "#demo5"
})