Vue 2.0组件间通信

2017-05-09  本文已影响0人  webHyman

组件的构成

组件意味着协同工作,通常父子组件会是这样的关系:组件 A 在它的模版中使用了组件 B 。它们之间必然需要相互通信:父组件要给子组件传递数据,子组件需要将它内部发生的事情告知给父组件。然而,在一个良好定义的接口中尽可能将父子组件解耦是很重要的。这保证了每个组件可以在相对隔离的环境中书写和理解,也大幅提高了组件的可维护性和可重用性。

解耦:耦合即依赖,两个组件间相互影响,解耦是为了减少两个组件间相互依赖的程度

在 Vue.js 中,父子组件的关系可以总结为 props down, events up 。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。看看它们是怎么工作的。


props-events.png

父子组件使用Props传递数据

组件实例的作用域是孤立的。这意味着不能并且不应该在子组件的模板内直接引用父组件的数据。可以使用 props 把数据传给子组件。

//parent
<template>
    <div>
        <Child :message="'I am parent Component'"></Child>
    </div>
</template>
<script>
    import Child from "./child.vue"
    export default{
        components:{
            Child
        },
    }
</script>
<template>
    <div>
        parent data : {{message}}
    </div>
</template>
<script>
    export default {
        props:{
//我们可以为组件的 props 指定验证规格。如果传入的数据不符合规格,
//Vue 会发出警告。当组件给其他人使用时,这很有用。注意这里是types
            message:{
                types:String
            }
        },
        data(){
            return {
                message : this.message
            }
        }
    }
</script>

单向数据流

prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解.
另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop 。如果你这么做了,Vue 会在控制台给出警告。
通常有两种改变 prop 的情况:
prop 作为初始值传入,子组件之后只是将它的初始值作为本地数据的初始值使用;
prop 作为需要被转变的原始值传入。
更确切的说这两种情况是:
定义一个本地数据,并且将 prop 的初始值设为本地数据的初始值。
定义一个基于 prop 值的计算属性。

注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。(可以通过在子组件中改变对象中的字段来改变父组件的值)

//parent
<template>
    <div>
      //将这个对象传给子组件
        <Child :message="'I am parent Component'" :obj="obj"></Child>
        <span>{{obj.name}}</span>
    </div>
</template>
<script>
    import Child from "./child.vue"
    export default{
        components:{
            Child
        },
        data(){
            return {
//在父组件中声明一个对象
                obj:{
                    name:"Hyman"
                }
            }
        }
    }
</script>
<template>
    <div>
        parent data : {{childMessage}}
    </div>
</template>
<script>
    export default {
        props:{
            message:{
                types:String
            },
            obj:{
                types:Object
            }
        },
        data(){
            return {
                childMessage : this.message
            }
        },
        created(){
            this.obj.name = "laowang"
        }
    }
</script>

非父子组件通信,Event Bus

有时候非父子关系的组件也需要通信。在简单的场景下,使用一个空的 Vue 实例作为中央事件总线:


event-bus.png
//新建一个eventBus.js文件进行统一管理
var bus = new Vue()
// 触发组件 A 中的事件(发布消息)
//引入eventBus.js 使用bus去发布消息
bus.$emit('id-selected', 1)
// 在组件 B 创建的钩子中监听事件(订阅消息)
//引入eventBus.js 使用bus去订阅消息
bus.$on('id-selected', function (id) {
// ...
})

show code

//parent
<template>
    <div>
        <FirstChild></FirstChild>
        <SecondChild></SecondChild>
    </div>
</template>
<script>
    import FirstChild from "./firstChild.vue"
    import SecondChild from "./secondChild.vue"
    export default{
        components:{
            FirstChild,
            SecondChild
        },
    }
</script>
//eventBus.js
//作为一个中央事件总线
import Vue from "vue";
export default new Vue;
//firstchild.vue
<template>
    <div id="firstChild">
        <button @click="sendMsg">向组件传值</button>
    </div>
</template>
<script>
    //注意引入的路径(根据实际情况来定)
    import bus from "./../../assets/eventBus.js"
    export default{
        data(){
            return {}
        },
        methods:{
            sendMsg:function(){
                bus.$emit("userDefinedEvent","the message from first child")
            }
        }
    }
</script>
//secondChild.vue
<template>
    <div id="secondChild">
        {{msg}}
    </div>
</template>
<script>
  //注意引入的路径(根据实际情况来定)
    import bus from "./../../assets/eventBus.js"
    export default{
        data(){
            return {
                msg : "default"
            }
        },
        mounted(){
            var self = this;
            bus.$on("userDefinedEvent",function(msg){
                self.msg = msg
            })
        }
    }
</script>

总结:

创建一个事件总线,例如demo中的eventBus,用它作为通信桥梁
在需要传值的组件中用bus.$emit触发一个自定义事件,并传递参数
在需要接收数据的组件中用bus.$on监听自定义事件,并在回调函数中处理传递过来的参数
在更多复杂的情况下,你应该考虑使用专门的 状态管理模式.

上一篇下一篇

猜你喜欢

热点阅读