VueProvideInject详细介绍(跨组件通信、响应式变化、版本
变化)
背景
通常,当我们需要从⽗组件向⼦组件传递数据时,我们使⽤ 。想象⼀下这样的结构:有⼀些深度嵌套的组件,⽽深层的⼦组件只需要⽗组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去,可能会很⿇烦。
对于这种情况,我们可以使⽤⼀对 provide 和 inject。⽆论组件层次结构有多深,⽗组件都可以作为其所有⼦组件的依赖提供者。这个特性有两个部分:⽗组件有⼀个 provide 选项来提供数据,⼦组件有⼀个 inject 选项来开始使⽤这些数据。
使⽤
假设有⼀个组件A,A组件引⼊B组件(A为B的⽗组件) ,B组件引⼊C组件(B为C的⽗组件),即A为C的祖先组件,此时⼆者可以使⽤provide / inject进⾏通信。
举例
A.vue
<template>
<div>
<B></B>
</div>
</template>
<script>
import B from "./B.vue";
export default {
name: "A",
components: {
B
},
};
</script>
B.vue
<C></C>
</div>
</template>
<script>
import C from "./C.vue";
export default {
长沙居住证name: "B",
components: {
C
},
};
</script>
C.vue
<template>
<div>
</div>
</template>
<script>
export default {
name: "C"
};
</script>
公司年会总结A与C使⽤provide / inject⽅式进⾏通信A使⽤provide
<template>
<div>
卵巢保养
<B></B>
</div>
</template>
<script>
import B from "./B.vue";
export default {
name: "A",
components: {
B
},
provide:{
name:"leo"
}
};
</script>
C使⽤inject
<span>{{name}}</span>
</div>
</template>
<script>
export default {
name: "C",
inject:["name"]
};
</script>
此时,C已经拿到A中的对应的name。但是,我们可能希望:当A中的name是本⾝某个可变化的数据时,如下:
<template>
<div>
<B></B>
</div>
</template>
<script>
import B from "./B.vue";
export default {
name: "A",
components: {
B
},
provide:{
name:this.name
},
data(){
return {
name:"leo"
牛肉炒土豆
}
},
methods:{
changeName(){
this.name = "lion"
}
}
};
</script>
名句古诗词
我们希望当name改变时(如触发changeName⽅法),对应的C中的name也要相应改变,但是使⽤以上⽅式时,C中的name并未随着改变,此时需要我们进⼀步处理,即处理响应性。
处理响应性
在上⾯的例⼦中,如果我们更改了name,这个变化并不会反映在 inject 的 name property 中。这是因为默认情况下,provide/inject 绑定并不是响应式的。在vue3中,我们可以通过传递⼀个 ref property 或 reactive 对象给 provide 来改变这种⾏为(下⾯展开)。在我们的例⼦(vue2)中,如果我们想对祖先组件中的更改做出响应,我们需要将 provide 传值进⾏改变。
A使⽤provide,此时传⼊的应是⼀个响应式对象(如以下的obj)
<B></B>
</div>
</template>
<script>
import B from "./B.vue";
export default {
name: "A",
components: {
B
},
provide(){
return {
obj:this.obj //传⼊⼀个响应式对象
}
},
data(){
return {
obj:{
name:"leo"
}
}
},
methods:{
changeName(){
this.obj.name = "lion"
}
}
};
</script>
C使⽤inject
<template>
<div>
<span>{{obj.name}}</span>
</div>
</template>
<script>
export default {
name: "C",
inject:["obj"] //接收响应式对象
};
</script>
此时A中的name改变,C中的值也会相应跟着变化。
以上为A向C传数据,如果C向A传数据(或者说C需要改变A中的数据),该如何做?
我们这⾥不让C直接改变A中的数据,⽽是将A改变数据的⽅法通过provide传给C,C执⾏该⽅法,触发改变A中的数据。A使⽤provide传⼊⼀个⽅法
<span>{{obj.name}}</span>
<B></B>
</div>
</template>
<script>
豆腐皮金针菇
import B from "./B.vue";
export default {
name: "A",
components: {
B
},
provide(){
return {
changeVal:this.changeName //传⼊⼀个⽅法
}
},
data(){
return {
obj:{
name:"leo"
}
}
},
methods:{经典武侠剧
changeName(val){ //C中触发该⽅法执⾏,此时变成"lion"
this.obj.name = val
}
}
};
</script>
C使⽤inject
<template>
<div>
<span @click="changeName">点击改变A组件数据</span>密阳
</div>
</template>
<script>
export default {
name: "C",
inject:["changeVal"], //接收⼀个⽅法
methods:{
changeName(){
this.changeVal("lion") //执⾏此⽅法,改变A中的数据
}
}
};
</script>
以上就是在vue2中对provide / inject的基本使⽤。
vue3中使⽤
Provide
在 tup() 中使⽤ provide 时,我们⾸先从 vue 显式导⼊ provide ⽅法。这使我们能够调⽤ provide 来定义每个 property。