porvide和inject是一套祖先组件往子孙组件注入依赖的方法,不管有多深,官方解释请移步→cn.vuejs.org/v2/api/#pro…
接下来我们来学习怎么使用provide:
1.对象的形式
provide: {
foo: "123"
},
这样书写很便捷,但有个弊端,就是传递的值只能是静态的,并且获取不到this,例如data、methods、computed里的都是获取不到的,这时我们就可以用另一种写法
2:工厂函数返回对象:
provide() {
return {
foo: this.bar//data中的值
brz: this.getSomeVal //methods中的方法
}
这种写法我们就可以传递this中的任意值。
接下来我们看看子组件中inject中是怎么接收他们的呢:
1.首先是最普通的以数组的形式接收
inject: ["foo"]
这里注意,数组内想要接收的祖先元素的键名必须是以字符串的形式书写,这种形式的弊端就是不够灵活,不能像props那样定义默认值,如果数组中涉及到的值祖先元素中没有就会导致报错,并且如果子孙组件中定义了和inject数组任意元素相应的名字的值的话,inject接收的数据就会被子孙组件中的同名数据覆盖,这样的体验是很差的,所有这里我们就可以以另一种形式来书写
2.对象的形式
someVal: {
//default:123,
//default:'dadada',
//default:() => [123,345,567]
from: "foo"
}
这样我们就可以很好的避免命名冲突,并且可以定义一些默认值,需要注意的是,如果我们定义的默认值是非原始值则需要使用一个工厂函数来返回
小技巧时间!
有时候我们不确定子孙组件到底会用到祖祖先组件中的什么数据,并且数据也不是响应式的当祖先组件传递的数据发生改变时并不会通知到子孙组件,以至于子孙组件的数据依旧是改变之前的数据,就像这样:
//祖先组件----------------------------------
provide() {
return {
foo: this.firstCreateComponent
}
},
data() {
return {
firstCreateComponent: true,
}
},
mounted() {
setTimeout(() => {
this.firstCreateComponent = false
},0)
}
//----------------------------------
//子孙组件----------------------------------
inject: ["foo"],
mounted: {
console.log(this.foo)//===>>>true
this.$forceUpdate()//进行一次强制更新
},
updated: {console.log(this.foo)},//===>>>true
从例子中可以看出,如果祖先组件中的数据发生了改变,并不会通知到子孙组件,对于某些场景来说这样的体验是不好的,所以我们就可以用到今天的小技巧:
//祖先组件----------------------------------
provide() {
return {
foo: this
}
},
//子孙组件----------------------------------
inject: ["foo"],
mounted: {
console.log(this.foo.someval)//===>> 获取data中的数据
console.log(this.foo.getVal())//===>>调用method中的方法
console.log(this.foo.calculation())//===>>调用computed中的方法
},
就像这样,祖先组件直接传递一个指向组件组件本身的this下去,这样子孙组件就可以直接使用this.foo.xxx的形式实时获取到祖先组件最新的值,一个很好用的小技巧哦!
~~对了对了,给自己挖个坑,下次给大家讲一下为什么inject和子孙组件中定义的值重名了会被覆盖,inject、data、method、computed、props他们的相互关系、优先级、先后顺序又设怎样的呢,等我来填坑哦~~~