一、Vue官方文档说明
在 Vue 中,父子组件的关系可以总结为 prop 向下传递,事件向上传递。父组件通过 prop给子组件下发数据,子组件通过事件给父组件发送消息。看看它们是怎么工作的。

- - - - - - - - - - - - - - - - ✂- - - - - - - - - - - - - -✂-- - - - - - -- - - - - - - -✂- - - - - - -- - - - - - - - - -
二、父子组件消息传递示例
1.父组件传递数据给子组件
父组件数据如何传递给子组件呢?
使用 Prop 传递数据
组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。父组件的数据需要通过 prop 才能下发到子组件中。
<parent>
<child :child-msg="msg"></child> //这里必须要用 - 代替驼峰
</parent>
data(){
return {
msg: [1,2,3]
};
}
子组件要显式地用
props
选项声明它预期的数据:
Vue.component('child', {
// 声明 props
props: ['childMsg'],
// 就像 data 一样,prop 也可以在模板中使用
// 同样也可以在 vm 实例中通过 this.childMsg 来使用
template: '<span>{{ childMsg }}</span>'
})
PS:
props
选项说明:
方式1:
props: ['childMsg']
方式2 :
props: {
childMsg: Array // 这样可以指定传入的类型,如果类型不对,会警告
}
方式3:
props: {
childMsg: {
type: Array,
default: [0,0,0] // 这样可以指定默认的值
}
}
这样呢,就实现了父组件向子组件传递数据
2.子组件与父组件通信
那么,如果子组件想要改变数据呢?这在vue中是不允许的,因为vue只允许单向数据传递,这时候我们可以通过触发事件来通知父组件改变数据,从而达到改变子组件数据的目的.
2.1 子组件:
<template>
<div @click="tellParent"></div>
</template>
methods: {
tellParent() {
this.$emit('toParent', 'Hi, father!'); // 主动触发toParent方法,'Hi, father!'为向父组件传递的数据
}
}
2.2 父组件:
<parent>
<child @toParent="change" :msg="msg"></child> // 监听子组件触发的toParent事件, 然后调用change方法
</parent>
methods: {
change(msg) {
this.msg = msg;
}
}
3.非父子组件通信
如果2个组件不是父子组件那么如何通信呢?这时可以通过eventHub来实现通信. 所谓eventHub就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件.
3.1 在共有组件中,创建一个空的 Vue 实例作为事件中心:
let Hub = new Vue(); //创建事件中心
组件1:
<template>
<a @click="event"></a>
</template>
methods: {
event () {
Hub.$emit('myEvent', 'Hi, there!'); // Hub触发事件自定义事件‘myEvent’,并传递信息“Hi, there!”
}
}
组件2:
<template>
<p>{{ message }}</p>
</template>
data() {
return {
message: '',
}
},
created() {
Hub.$on('myEvent', (msg) => { // Hub接收事件“myEvent”,并接受传递的信息msg
this.message = msg;
});
}
这样就实现了非父子组件之间的通信了.原理就是把Hub当作一个中转站!
3.2 在main.js(vue-cli脚手架创建的项目)中,给data添加一个 名字为Hub的空vue对象
这时候,在任何组件都可以调用事件发射 接受的方法了。
// 根组件(this.$root)
new Vue({
el: '#app',
router,
render: h => h(App),
data: {
// 空的实例放到根组件下,所有的子组件都能调用
Hub: new Vue()
}
})
假设 B 组件里面有个按钮,点击按钮,把 123 传递给 A 组件
3.2.1 B组件内调用事件触发↓
<button @click="submit">提交<button>
methods: {
submit() {
// 通过this.$root.Hub获取此对象,再调用$emit方法
this.$root.Hub.$emit('YOUR_EVENT_NAME', 123)
}
}
A组件内调用事件接收↓
// 当前实例创建完成就监听这个事件
created(){
this.$root.Hub.$on('YOUR_EVENT_NAME', (yourData) => {
handle(yourData)
})
},
methods: {
handle(yourData) {
console.log(yourData)
}
},
// 在组件销毁时别忘了解除事件绑定
beforeDestroy() {
this.$root.Hub.$off('YOUR_EVENT_NAME')
},