1. 概念
父辈们给祖孙传值, 不论子组件有多深,只要调用了inject那么就可以注入provider中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,这就是它最大的特性。
2. 基本用法
provide 选项应该是:一个对象或返回一个对象的函数
inject 选项应该是:一个字符串数组,或 一个对象,对象的 [key] 是本地的绑定名
2.1 代码执行顺序:
data
provide
created//在这个阶段$el还未生成,在这先处理privide的逻辑,子孙组件才可以取到inject值
mounted
2.2 demo
parent父页面:
export default {
data(){
return {
fonnB: 'old word'
}
},
provide() {
return {
foo: this.fonnB
}
},
created() {
setTimeout(()=>{
this.fonnB = "new words";
// 这里foo变化了,但子组件获得的foo 依旧是old words
},1000)
},
}
child子页面:
export default {
inject:['foo'],
created () {
console.log(this.foo)
// -> 'old word'
setTimeout(() => {
console.log(this.foo); // 这里计算属性依旧是old words
}, 2000);
}
}
实现响应式
上面的demo问题已经暴露出来了,那就是上级的属性改变了,但是子孙后面通过inject接收的值却不改变
在vue官方文档中有这么一句话
提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
解决:
parent父页面:
export default {
data(){
return {
fonnB: 'old word'
}
},
provide() {
return {
foo: () => this.fonnB //这里通过一个函数返回值的方式,传入的是一个function 是一个值的引用
}
},
created() {
setTimeout(()=>{
this.fonnB = "new words";
},1000)
},
}
child子页面:
export default {
inject:['foo'],
computed:{
chilrdfoo(){
return this.foo() //通过计算属性调用inject传进来的函数,返回值
}
}
created () {
console.log(this.foo)
setTimeout(() => {
console.log(this.chilrdfoo); // 这里就可以获取到最新的值的改变了
}, 2000);
}
}
params: { foo: this.foo}, // value 是对象才能实现响应式,也就是引用类型