inject/provide与响应式数据
provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。说人话就是如果你把对象都改了那这个改动就追踪不到了,如果你就改了个对象属性那这种响应就能追踪到。以下是具体的代码分析。这意味着,出于某种考虑,vue故意将provide/inject设定为不可响应的。也就是说如果你的provide的数据改变,inject是不会接受
provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
说人话就是如果你把对象都改了那这个改动就追踪不到了,如果你就改了个对象属性那这种响应就能追踪到。以下是具体的代码分析。
这意味着,出于某种考虑,vue故意将provide/inject设定为不可响应的。也就是说如果你的provide的数据改变,inject是不会接受到这个改变,然而如果你provide的内容是一个可响应的数据,比如一个对象引用,那么这个对象的属性是可以检测到变化的。举例来说:
provide(){
return{
foo:this.msg
}
},
data() {
return {
msg: "hello",
}
}
mounted(){
setTimeout(()=>{
this.msg = "world";
},3000)
}
而此时你在子组件中去监测:
inject:{
foo: { default: {} }
}
就会发现不管父组件的foo怎么更改,子组件的foo都不会改变。
而如果你改变的不是对象,而是对象的属性,那么这个改变就可以被监测,举例来说:
provide(){
return{
foo: this.msg
}
},
data() {
return {
msg: {
bar: 'hello'
}
}
}
mounted(){
setTimeout(()=>{
this.msg.bar = "world";
},3000)
}
那么此时子组件就可以监听到属性的变动。
这里有一个重点,这个属性更改是以引用不变前提下的属性更改,如果引用变动了,那就是对象改变而不是对象的属性改变了。举个例子:
mounted(){
setTimeout(()=>{
// 这种情况下叫改变了属性,属性的更改是可以响应的
this.msg.bar = "world";
// 这种情况就是对对象的重新赋值,也就是把对象引用都改了,这种是不可响应的
this.msg = {
bar: 'world'
}
},3000)
}
看到了响应式的问题已经解决了,inject也确实会随着provide的属性变更而改变数据。
但是怀着打破砂锅问到底的方针,这种改变是否可以被本地监测呢?像这样data和computed数据是可响应的吗?如下:
data() {
return {
data: this.boardData.data
};
},
inject: {
boardData: { default: {} }
},
computed: {
data1() {
return this.boardData.data;
}
}
经过严谨的实验,答案是不能,因此尽管号称inject/provide是类似于props这种父子组件传值的,祖孙组件传值,但是实现方式并不相同。
结果如下:
因此需要用的inject的计算值的时候还是直接算,不要指望能用computed取返回响应的计算值了
更多推荐


所有评论(0)