对于使用Vue的新手来说,组件之间的数据传递是一个比较麻烦的问题,在开发中我自己也踩了不少坑,这篇文章简单地做了一个总结。

首先,在 Vue 中,父子组件的关系可以总结为 props down, events up。父组件通过 props 向下传递数据给子组件,子组件通过 events 给父组件发送消息。如下图:

目录

  • 1. 父子组件之间的数据传递
    • 1.1 父组件向子组件传递数据
    • 1.2 子组件向父组件传递事件
  • 2. 非父子关系组件之间的数据传递

父子组件之间的数据传递

父组件向子组件传递数据

组件实例的作用域(scope)是孤立的,所以组件之间无法相互访问到对方的数据,所以这里我们需要在子组件中使用props选项去接受来自父组件传递进来的动态数据,并且在父组件的标签上绑定v-bind该数据,这样一来,我们就把父组件中的数据传递给了子组件中。

// 创建父组件
Vue.component("m-super", {
    data: ()=>{
        return {
            message: "Hello Super"
        }
    },
    template: `<div>
            <input placeholder='请输入message的值' v-model='message'></input>
            <br/>
            <m-child :message='message'></m-child>
            </div>`
});

// 创建子组件,并需要把父组件的message的值传递给子组件
Vue.component("m-child", {
    props: ["message"],
    template: "<span>子组件显示:{{ message }}</span>"
})

props数据是单向传递

props是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。

这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。

每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop。如果你这么做了,Vue 会在控制台报错。如下:

[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "message"

子组件向父组件传递事件

因为prop是单向数据流的,所以prop接受的数据是无法双向绑定的,那么如何改变父组件的数据呢——使用vue自定义事件

  • 子组件中我们可以通过$emit(eventName)来触发事件
  • 父组件中我们可以通过$on(eventName)来监听事件

下面给子组件添加了一个重置按钮,一按就可以将父组件的值改为Hello Child。代码如下:

// 创建父组件
Vue.component("m-super", {
    data: ()=>{
        return {
            message: "Hello Super"
        }
    },
    template: `<div>
            <input placeholder='请输入message的值' v-model='message'></input>
            <br/>
            <m-child :message='message' v-on:reset="reset"></m-child>
            </div>`,
    methods:{
        reset:function(e){
            this.message = e
        }
    }
});

// 创建子组件,并需要把父组件的message的值传递给子组件
Vue.component("m-child", {
    props: ["message"],
    template: "<div><span>子组件显示:{{ message }}</span><br/><button v-on:click='reset()'>重置</button></div>",
    methods: {
        reset:function(){
            this.$emit("reset", "Hello child")
        }
    }
})

这样一来,我们便实现了父子组件数据的双向绑定。

非父子组件之间的数据传递

对于非父子组件通信情况,在简单的场景下,可以使用一个空的Vue实例作为中央事件总线:

var bus = new Vue()
// 触发组件 A 中的事件
bus.$emit('id-selected', 1)
// 在组件 B 创建的钩子中监听事件
bus.$on('id-selected', function (id) {
// ...
})

如果非父子组件通信比较复杂时,我们可以通过Vuex来解决。


欢迎关注我的微信公众号
![](http://upload-images.jianshu.io/upload_images/3093748-7c07998b7495defc.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)