provide-inject 跨层通信收藏我的收藏
收藏
我的收藏基础库 2.62.0 开始支持。
provide-inject 是一种允许祖先组件跨多层向后代组件传递内容的通信方式。
对于层层嵌套的组件,祖先组件可以通过一个
provide
选项来提供数据,后代组件可以通过声明 inject
选项注入(开始使用)这些数据。声明了 inject
选项的组件被称为 inject 组件,为 inject 组件提供数据的祖先组件被称为 provide 组件。provide 组件不需要知道哪些后代组件使用它提供的数据,inject 组件也不需要知道注入的数据来自哪个 provide 组件。使用前配置
默认情况下,provide-inject 能力是关闭的,如果开发者想使用 provide-inject 能力,需要在
app.json
声明以下字段:{ "usingProvide": true }
开启 provide-inject 能力前,请检查旧代码,如果在 Page 函数或 Component 函数的参数对象中定义了
provide
、inject
、setProvide
字段之一或在自定义组件的 methods
字段中定义了 setProvide
方法 ,请使用其他的名字替换,除非开发者清楚自己确实正在使用 provide-inject 能力。数据提供与数据注入
假设存在自定义组件 A、B、C 依次嵌套, 结构如下所示。
A └── B └── C
如果需要将组件 A 的某个数据传给组件 C,只需要分别在组件 A 和 组件 C 声明
provide
选项和 inject
选项,代码如下:// 组件 A 的 js Component({ data: { app: "toutiao", }, provide() { // 返回值就是要提供的数据 return { providedA: this.data.app, }; }, }); // 组件 C 的 js Component({ data: { c: "douyin", }, inject: ["providedA"], // 从组件 A 中获取 providedA 的值,即 'toutiao' ready() { this.setData( { c: this.inject.providedA, }, () => { console.log(this.data.c); // 'toutiao } ); }, });
provide 说明
- •
provide
作为 Component
函数或 Page
函数的参数对象的一个可选字段使用。- •
provide
类型是 function
,返回值是一个数据对象,这个数据对象的 key 就是能被 inject 组件检索的属性名,value 是实际提供的值,可以是任何值。- •
provide
函数的 this
指向组件实例本身,因此在函数体内可以通过 this.data
、this.properties
、this.inject
、this
分别访问到自身的数据、属性、注入数据和组件方法 。- •在组件或页面初始化的时候如果存在
provide
选项并且 provide
选项是一个函数,就会执行 provide
函数。函数的执行时机在自定义组件触发生命周期 created 或页面触发生命周期 load 之前。inject 说明
- •
inject
作为自定义组件的 Component
函数的参数对象的字段使用。- •
inject
声明可以从祖先 provide 组件获取的数据。如果祖先存在多个 provide 组件声明了同一个 key, inject 组件注入此 key 时选择的是最近 provide 组件的 key。- •
inject
类型可能是以下其中一种:- ◦
string[]
,每个元素表示注入的 key,需要 provide 组件提供同名的 key 才能拿到注入值到 inject 组件中。 - ◦
object
,对象的 key 是 inject 组件注入的 key 名,类型为 string | symbol
, inject 组件可以通过 this.inject[key]
访问 provide 组件的数据,value 的类型可以是:- ▪
string | symbol
,表示在 provide 组件搜索用的 key。- ▪
object
,有from
和 default
两个可选字段,其中:from
是在 provide 组件中搜索用的 key,用于取别名。比如 a: {from: 'b'}
会将 provide 组件的提供的 b
映射到 inject 组件的 this.inject.a
上;default
是在 provide 组件找不到 key 时使用的默认值。可以是任何类型,如果 default
是一个函数,则找不到 key 时,在组件初始化的时候会自动执行 default
函数,函数的返回值作为 this.inject[key]
的值数据的更新
如果需要将组件 A 提供的
providedA
的值更新为其他值, 比如从 this.data.app
更新为 "xigua"
,可以在 provide 组件中使用 setProvide
函数实现,代码如下:<!-- 组件 A 的 ttml --> <button bindtap="methodA">点击更新 provide</button>
// 组件 A 的 js Component({ data: { app: "toutiao", }, provide() { // 返回值就是要提供的数据 return { providedA: this.data.app, }; }, methods: { methodA() { this.setProvide({ providedA: "xigua", }); }, }, }); // 组件 C 的 js Component({ data: { c: "douyin", }, inject: ["providedA"], // 从组件 A 中获取 providedA 的值,即 'toutiao' ready() { this.setData( { c: this.inject.providedA, }, () => { console.log(this.data.c); // 'toutiao } ); }, observers: { // 点击组件 A 的 button 后,触发该监听器的执行 providedA(val) { console.log(val); // 'xigua' console.log(val === this.inject.providedA); // true }, }, });
setProvide 说明
- •
setProvide
是 Component 或 Page 实例上的一个方法。- •
setProvide
类型是function
,函数参数是一个数据对象,数据对象的 key 是 provide 组件需要被更新的 key,必须是 provide
函数返回对象中已经声明过的 key,setProvide
用于更新 provide 组件向后代 inject 组件提供的数据,可以触发 inject 组件的 对更新字段的监听回调。- •
setProvide
的执行不会触发页面的重新渲染。注入的 key 的别名机制
observers 可以对
this.inject
的字段进行监听,如同对 this.data
的字段监听一样,当 this.inject
的 字段和 this.data
的字段重复时,observers 只能监听 this.inject
的字段。inject 组件可以通过给注入的 key 取别名的方式规避 this.inject
的字段和 this.data
的字段重复的问题。代码如下:// 组件 A 的 js Component({ data: { app: "toutiao", }, provide() { // 返回值就是要提供的数据 return { providedA: this.data.app, }; }, }); // 组件 C 的 js Component({ inject: { fromProvidedA: "providedA", // 将 providedA 映射成别名 fromProvidedA }, ready() { console.log(this.inject.providedA); // undefined console.log(this.inject.fromProvidedA); // 'toutiao' }, }); // 另一种写法 // 组件 C 的 js Component({ inject: { fromProvidedA: { from: "providedA", // 将 providedA 映射成别名 fromProvidedA }, }, ready() { console.log(this.inject.providedA); // undefined console.log(this.inject.fromProvidedA); // 'toutiao' }, });
注入的 key 的默认值
如果 inject 组件在
inject
选项声明了一个 key,该 key 无法在任何一个祖先组件中找到,则 this.inject[key]
的结果为 undefined
。 通过在 inject
选项声明 default
字段的方式,可以在 inject 组件找不到能够提供某个 key 的祖先组件的情况下,将默认值赋给 this.inject[key]
。代码如下:// 组件 C 的 js Component({ inject: { notExist: { default: "tomato", }, }, ready() { console.log(this.inject.notExist); // 'tomato' }, });
如果
default
字段声明成一个函数,则取 default
函数的返回值作为 this.inject[key]
的默认值, default
函数的 this
指向组件实例自身。// 组件 C 的 js Component({ data: { a: 1, }, inject: { notExist: { default() { return this.data.a + 1; }, }, }, ready() { console.log(this.inject.notExist); // 2 }, });