Vue组件之间的通信方式包括props、$emit、$attrs、$parent、$children、$refs、event bus和Vuex。其中,props和$emit是父子组件之间通信的常用方式,$parent/$children和$refs适用于父子组件之间的直接通信,event bus适用于任意组件之间的通信,而Vuex则适用于大型应用中的状态管理。它们的优缺点如下:
props
父组件向子组件传递数据,简单易用,但只能单向传递数据。
// 父组件
<Chilren1 :aa="'单向传值'"></Chilren1>
// 子组件
props: {
aa: String
}
// 或
props: ['aa']
双向绑定需要这样
provide&inject
provide与inject是Vue中的高级组件通信方式,它们可以让父组件向子孙组件传递数据,而不需要通过props或者事件来传递。provide是在父组件中定义一个数据或者方法,然后通过一个对象将其传递给子组件。子组件可以通过inject选项来注入这些数据或者方法,然后在子组件中使用。需要注意的是,provide和inject并不是响应式的,也不会进行类型检查,因此需要谨慎使用。另外,provide和inject的使用应该遵循单向数据流的原则,即父组件提供数据,子组件使用数据,而不应该反过来。很奇怪,不建议使用
// 父组件
export default {
provide () {
return {
message: this.message
}
},
data () {
return {
message: 'Hello World', //改变message时子孙组件接收的值不会动态改变,Array亦不会变
// 或
message: { //改变message的属性时,子孙组件接收的值会动态改变
a: 'Hello',
b: 'World'
}
}
}
// 子孙组件
export default {
inject: ['message'],
mounted() {
console.log(this.message) // 输出:Hello World
}
}
$attrs & $listeners
$attrs:祖先传递数据给子孙,父组件向子组件传递数据–包含了父级作用域中不作为 prop 被识别 (且获取) 的特性绑定 ( class 和 style 除外)。
$listeners:祖先传递事件给子孙,包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=“$listeners” 传入内部组件
// 父组件
<Chilren1 :aa="'单向传值'" bb='将会传给$attrs' v-on:click='fatherFun'></Chilren1>
fatherFun () {
console.log('这是父组件函数')
}
// 子组件Chilren1
<template>
{{ $attrs }} // { bb: '将会传给$attrs' }
<GrandSon v-bind="$attrs" v-on:click='sonFun' v-on="$listeners"></GrandSon>
// 此时$listeners是父作用域中的 (不含 .native 修饰器的) v-on 事件监听器
</template>
sonFun () {
console.log('这是子组件函数')
this.$emit('click')
// sonFun执行结果:这是子组件函数 这是父组件函数
}
props: {
aa: String
}
// 孙子组件GrandSon
<div @click="grandSonFun">
{{ bb }} // 显示文字:将会传给$attrs
</div>
props: {
bb: String
}
grandSonFun () {
console.log('这是孙子组件函数')
this.$emit('click')
// grandSonFun执行结果:这是孙子组件函数 这是父组件函数
}
$emit
子组件向父组件传递数据,也只能单向传递数据。
// 父组件
<Chilren1 @father='fatherFun'></Chilren1>
fatherFun () {
console.log('这是父组件函数')
}
// 子组件Chilren1
<template>
<div v-bind="$attrs" @click='sonFun'></div></template>
sonFun () {
console.log('这是子组件函数')
this.$emit('fatherFun')
// sonFun执行结果:这是子组件函数 这是父组件函数
}
$parent & $children
直接访问父组件或子组件的实例,但不够灵活,不适用于跨级通信。注意:节制地使用 $parent 和 $children,它们的主要目的是作为访问组件的应急方法。更推荐用 props 和 events 实现父子组件通信。
this.$parent
// or
this.$children
$refs
通过ref属性访问子组件的实例,但也不够灵活,只适用于父子组件之间的通信。
<Children ref="foo" />
this.$refs.foo // 父组件由此可以获取子组件的数据
EventBus
通过事件总线实现任意组件之间的通信,灵活方便,但需要手动管理事件的订阅和取消订阅。
Vuex
适用于大型应用中的状态管理,可以方便地管理全局状态,但增加了一定的复杂度。
小结
父子关系的组件数据传递选择 props 与 $emit进行传递,也可选择ref
兄弟关系的组件数据传递可选择$bus,其次可以选择$parent进行传递
祖先与后代组件数据传递可选择attrs与listeners或者Provide与 Inject
复杂关系的组件数据传递可以通过vuex存放共享的变量