爷孙组件通信
顾名思义,爷孙组件是比 父子组件通信 要更深层次的引用关系(也有称之为 “隔代组件”):
Grandfather.vue
└─Son.vue
└─Grandson.vue
方案
因为上下级的关系的一致性,爷孙组件通信的方案也适用于 父子组件通信 ,只需要把爷孙关系换成父子关系即可。
provide / inject
Grandfather.vue 有一个 provide 选项来提供数据,Grandson.vue 有一个 inject 选项来开始使用这些数据。
- Grandfather.vue 通过 provide 向 Grandson.vue 传值(可包含定义好的函数)
- Grandson.vue 通过 inject 向 Grandfather.vue 触发爷爷组件的事件执行
来看一下如何创建一个 provide:
import { defineComponent, provide } from 'vue'
export default defineComponent({
setup () {
const msg: string = 'Hello World!';
provide('msg', msg);
}
})
需要注意的是,provide 不是响应式的,如果你要使其具备响应性,你需要传入响应式数据
接收 inject
import { defineComponent, inject } from 'vue'
export default defineComponent({
setup () {
const msg: string = inject('msg') || '';
}
})
响应性数据的传递与接收
先在 Grandfather.vue 里 provide 数据:
export default defineComponent({
setup () {
const msg = ref<string>('Hello World!');
provide('msg', msg);
const userInfo: Member = reactive({
id: 1,
name: 'Petter'
});
provide('userInfo', userInfo);
setTimeout(() => {
msg.value = 'Hi World!';
userInfo.name = 'Tom';
}, 2000);
}
})
在 Grandsun.vue 里 inject 拿到数据:
export default defineComponent({
setup () {
const msg = inject('msg');
const userInfo = inject('userInfo');
console.log(msg);
console.log(userInfo);
setTimeout(() => {
console.log(msg);
console.log(userInfo);
}, 3000);
return {
msg,
userInfo
}
}
})
响应式的数据 provide 出去,在子孙组件拿到的也是响应式的,并且可以如同自身定义的响应式变量一样,直接 return 给 template 使用,一旦数据有变化,视图也会立即更新。
但上面这句话有效的前提是,不破坏数据的响应性,比如 ref 变量,你需要完整的传入,而不能只传入它的 value,对于 reactive 也是同理,不能直接解构去破坏原本的响应性。
|