provide inject 跨组件传参 + 响应式数据
父组件与子组件的传参,使用的是props,如果是父组件与孙子组件传参,大部分可能会采用递归的方式,也就是子组件props接收,然后再props传给孙子组件。或者使用vuex。
但如果是迭代的方式,组件的层级越深,不断迭代的props会是代码越来越无法维护,冗余。
于是官方出了provide inject。
provide有父组件设置,inject由子组件接收,他们的特性:
- 祖先组件不需要知道哪些后代组件使用它提供的属性
- 后代组件不需要知道被注入的属性来自哪里
例子:
父组件
<script>
export default {
provide: {
foo: 'bar'
},
}
</script>
孙子组件
<script>
export default {
inject: ['foo'],
}
</script>
用法和props差不多,inject也有default属性
<script>
export default {
inject: {
foo:{
default:"默认值"
}
}
}
</script>
如果默认的是一个引用类型,也要像props一样,用一个工厂函数抛出
<script>
export default {
inject: {
foo:{
default: ()=> [1,2,3]
}
}
}
</script>
如果inject里的key和其他属性发生了冲突,我们可以像model那样,有一个声明
<script>
export default {
inject: {
foo1:{
from: "foo",
default: ()=> [1,2,3]
}
}
}
</script>
from表示其源。
提示:provide
和inject
绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
也就是说,如果传入的是非引用类型的值,父组件修改provide中的属性值,孙子组件并不会响应其变化。
如果是一个引用类型,那么是可以响应到父组件的变化,我们甚至可以使用一个函数来达到响应变化的效果
响应式
函数方式
父组件
<script>
export default {
data(){
return {
color:"blue"
}
},
provide() {
return {
color: this.getColor
}
},
methods:{
getColor() {
return this.color;
},
}
}
</script>
孙子组件
<template>
<span>{{color()}}</span>
</template>
<script>
export default {
inject: ['color'],
}
</script>
通过函数的方式,当父组件中data的color的值发生了变化,子组件依旧可以响应到。
注意一点,如果是传string,可以使用provide为一个对象的形式,如果你要在provide的里面通过this,来获取上下文数据,那么就要如上,使用方法的形式,return出一个对象才行。
性能上估计不太好。
引用类型{}
<script>
export default {
data(){
return {
color:{
get:"blue"
}
}
},
provide() {
return {
color: this.color
}
},
}
</script>
孙子组件
<template>
<span>{{color.get}}</span>
</template>
<script>
export default {
inject: ['color'],
}
</script>
这样依旧可以响应到变化,但是不怎么建议使用。
Vue.observable()
这是vue 2.6版本新增的一个api,用于创建一个可监控的对象,大概用起来和vuex相差不了多少,感觉就是一个小型vuex的快速建成方式。
父组件
<script>
import Vue from "vue";
export default {
provide() {
this.theme = Vue.observable({
color: "blue",
});
return {
theme: this.theme,
};
},
}
</script>
孙子组件
<template>
<span>{{theme.color}}</span>
</template>
<script>
export default {
inject: ['theme'],
}
</script>
这样也可以响应到父组件的color值变化。
但是必须是vue 2.6版本,vue-template-compiler也要同步
//升级vue版本npm
update vue -S
//或者
yarn add vue -Snpm update vue-template-compiler -D
//或者
yarn add vue-template-compiler -D
Vue.observable如何更新数据
你可以直接this.theme.color="xxx"
来更新,也可以封装一个类似于vuex的mutation方法对象集合。
import vue from 'vue';
export const store = vue.observable({count: 0});
export const mutation = {
setCount( count ){
store.count = count;
}
}
这种方式可以单独做个js文件,也可以改动一下丢在组件内。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据