美文网首页
Vue 2.0组件间通信

Vue 2.0组件间通信

作者: webHyman | 来源:发表于2017-05-09 18:35 被阅读0次

    组件的构成

    组件意味着协同工作,通常父子组件会是这样的关系:组件 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监听自定义事件,并在回调函数中处理传递过来的参数
    在更多复杂的情况下,你应该考虑使用专门的 状态管理模式.

    相关文章

      网友评论

          本文标题:Vue 2.0组件间通信

          本文链接:https://www.haomeiwen.com/subject/mrnbtxtx.html