抖音开放平台Logo
开发者文档
“/”唤起搜索
控制台

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 函数的参数对象中定义了 provideinjectsetProvide 字段之一或在自定义组件的 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.datathis.propertiesthis.injectthis 分别访问到自身的数据、属性、注入数据和组件方法 。
    在组件或页面初始化的时候如果存在 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,有fromdefault两个可选字段,其中: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 }, });