• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ComponentContent
2<!--Kit: ArkUI-->
3<!--Subsystem: ArkUI-->
4<!--Owner: @liyi0309-->
5<!--Designer: @liyi0309-->
6<!--Tester: @lxl007-->
7<!--Adviser: @HelloCrease-->
8
9ComponentContent表示组件内容的实体封装,其对象支持在非UI组件中创建与传递,便于开发者对弹窗类组件进行解耦封装。其底层使用了BuilderNode,具体使用规格参考[BuilderNode](js-apis-arkui-builderNode.md)。
10
11> **说明:**
12>
13> 本模块从API version 12开始支持。后续版本的新增接口,采用上角标单独标记接口的起始版本。
14>
15> 当前不支持在预览器中使用ComponentContent。
16
17
18## 导入模块
19
20```ts
21import { ComponentContent } from '@kit.ArkUI';
22```
23
24## ComponentContent
25
26继承自[Content](js-apis-arkui-Content.md#content-1)。
27
28**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
29
30**系统能力:** SystemCapability.ArkUI.ArkUI.Full
31
32### constructor
33
34constructor(uiContext: UIContext, builder: WrappedBuilder\<[]>)
35
36ComponentContent的构造函数。
37
38**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
39
40**系统能力:** SystemCapability.ArkUI.ArkUI.Full
41
42**参数:**
43
44| 参数名    | 类型                                      | 必填 | 说明                               |
45| --------- | ----------------------------------------- | ---- | ---------------------------------- |
46| uiContext | [UIContext](./arkts-apis-uicontext-uicontext.md) | 是   | 创建对应节点时所需要的UI上下文。 |
47| builder  | [WrappedBuilder\<[]>](../../ui/state-management/arkts-wrapBuilder.md) | 是   |   封装不带参builder函数的WrappedBuilder对象。 |
48
49### constructor
50
51constructor(uiContext: UIContext, builder: WrappedBuilder\<[T]>, args: T)
52
53ComponentContent的构造函数。
54
55**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
56
57**系统能力:** SystemCapability.ArkUI.ArkUI.Full
58
59**参数:**
60
61| 参数名    | 类型                                      | 必填 | 说明                               |
62| --------- | ----------------------------------------- | ---- | ---------------------------------- |
63| uiContext | [UIContext](./arkts-apis-uicontext-uicontext.md) | 是   | 创建对应节点时候所需要的UI上下文。 |
64| builder  | [WrappedBuilder\<[T]>](../../ui/state-management/arkts-wrapBuilder.md) | 是   |   封装带参builder函数的WrappedBuilder对象。 |
65| args     |     T     |   是   |   WrappedBuilder对象封装的builder函数的参数。 |
66
67### constructor
68
69  constructor(uiContext: UIContext, builder: WrappedBuilder\<[T]>, args: T, options: BuildOptions)
70
71ComponentContent的构造函数。
72
73**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
74
75**系统能力:** SystemCapability.ArkUI.ArkUI.Full
76
77**参数:**
78
79| 参数名    | 类型                                      | 必填 | 说明                               |
80| --------- | ----------------------------------------- | ---- | ---------------------------------- |
81| uiContext | [UIContext](./arkts-apis-uicontext-uicontext.md) | 是   | 创建对应节点时候所需要的UI上下文。 |
82| builder  | [WrappedBuilder\<[T]>](../../ui/state-management/arkts-wrapBuilder.md) | 是   |   封装带参builder函数的WrappedBuilder对象。 |
83| args     |     T     |   是   |   WrappedBuilder对象封装的builder函数的参数。 |
84| options | [BuildOptions](./js-apis-arkui-builderNode.md#buildoptions12)                                                    | 是   |  build的配置参数,判断是否支持@Builder中嵌套@Builder的行为。                                         |
85
86**示例:**
87``` ts
88import { ComponentContent, NodeContent, typeNode } from "@kit.ArkUI";
89
90interface ParamsInterface {
91  text: string;
92  func: Function;
93}
94
95@Builder
96function buildTextWithFunc(fun: Function) {
97  Text(fun())
98    .fontSize(50)
99    .fontWeight(FontWeight.Bold)
100    .margin({ bottom: 36 })
101}
102
103@Builder
104function buildText(params: ParamsInterface) {
105  Column() {
106    Text(params.text)
107      .fontSize(50)
108      .fontWeight(FontWeight.Bold)
109      .margin({ bottom: 36 })
110    buildTextWithFunc(params.func)
111  }
112}
113
114@Entry
115@Component
116struct Index {
117  @State message: string = "HELLO";
118  private content: NodeContent = new NodeContent();
119
120  build() {
121    Row() {
122      Column() {
123        Button('addComponentContent')
124          .onClick(() => {
125            let column = typeNode.createNode(this.getUIContext(), "Column");
126            column.initialize();
127            column.addComponentContent(new ComponentContent<ParamsInterface>(this.getUIContext(),
128              wrapBuilder<[ParamsInterface]>(buildText), {
129                text: this.message, func: () => {
130                  return "FUNCTION"
131                }
132              }, { nestingBuilderSupported: true }));
133            this.content.addFrameNode(column);
134          })
135        ContentSlot(this.content)
136      }
137      .id("column")
138      .width('100%')
139      .height('100%')
140    }
141    .height('100%')
142  }
143}
144
145```
146
147### update
148
149update(args: T): void
150
151用于更新[WrappedBuilder](../../ui/state-management/arkts-wrapBuilder.md)对象封装的builder函数参数,与constructor传入的参数类型保持一致。
152
153**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
154
155**系统能力:** SystemCapability.ArkUI.ArkUI.Full
156
157**参数:**
158
159| 参数名 | 类型 | 必填 | 说明                                                         |
160| ------ | ---- | ---- | ------------------------------------------------------------ |
161| args   | T    | 是   | 用于更新[WrappedBuilder](../../ui/state-management/arkts-wrapBuilder.md)对象封装的builder函数参数,与constructor传入的参数类型保持一致。 |
162
163**示例:**
164
165```ts
166import { ComponentContent } from "@kit.ArkUI";
167
168class Params {
169  text: string = "";
170  constructor(text: string) {
171    this.text = text;
172  }
173}
174
175@Builder
176function buildText(params: Params) {
177  Column() {
178    Text(params.text)
179      .fontSize(50)
180      .fontWeight(FontWeight.Bold)
181      .margin({bottom: 36})
182  }.backgroundColor('#FFF0F0F0')
183}
184
185@Entry
186@Component
187struct Index {
188  @State message: string = "hello";
189
190  build() {
191    Row() {
192      Column() {
193        Button("click me")
194            .onClick(() => {
195                let uiContext = this.getUIContext();
196                let promptAction = uiContext.getPromptAction();
197                let contentNode = new ComponentContent(uiContext, wrapBuilder(buildText), new Params(this.message));
198                promptAction.openCustomDialog(contentNode);
199
200                setTimeout(() => {
201                  contentNode.update(new Params("new message"));
202                }, 2000);    //2秒后自动更新弹窗内容文本
203            })
204      }
205      .width('100%')
206      .height('100%')
207    }
208    .height('100%')
209  }
210}
211```
212
213### reuse
214
215reuse(param?: Object): void
216
217触发ComponentContent中的自定义组件的复用。组件复用请参见[@Reusable装饰器:组件复用](../../ui/state-management/arkts-reusable.md)。关于ComponentContent的解绑场景请参见[解除实体节点引用关系](../../ui/arkts-user-defined-arktsNode-builderNode.md#解除实体节点引用关系)。
218
219**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
220
221**系统能力:** SystemCapability.ArkUI.ArkUI.Full
222
223**参数:**
224
225| 参数名 | 类型   | 必填 | 说明                                                                     |
226| ------ | ------ | ---- | ------------------------------------------------------------------------ |
227| param  | Object | 否   | 用于复用WrappedBuilder对象封装的builder函数参数,与constructor传入的参数类型保持一致。 |
228
229### recycle
230
231recycle(): void
232
233- 触发ComponentContent中自定义组件的回收。自定义组件的回收是组件复用机制中的环节,具体信息请参见[@Reusable装饰器:组件复用](../../ui/state-management/arkts-reusable.md)。
234- ComponentContent通过reuse和recycle完成其内外自定义组件之间的复用事件传递,具体使用场景请参见[BuilderNode调用reuse和recycle接口实现节点复用能力](../../ui/arkts-user-defined-arktsNode-builderNode.md#buildernode调用reuse和recycle接口实现节点复用能力)。
235
236**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
237
238**系统能力:** SystemCapability.ArkUI.ArkUI.Full
239
240```ts
241import { NodeContent, typeNode, ComponentContent } from "@kit.ArkUI";
242
243const TEST_TAG: string = "Reuse+Recycle";
244
245class MyDataSource {
246  private dataArray: string[] = [];
247  private listener: DataChangeListener | null = null;
248
249  public totalCount(): number {
250    return this.dataArray.length;
251  }
252
253  public getData(index: number) {
254    return this.dataArray[index];
255  }
256
257  public pushData(data: string) {
258    this.dataArray.push(data);
259  }
260
261  public reloadListener(): void {
262    this.listener?.onDataReloaded();
263  }
264
265  public registerDataChangeListener(listener: DataChangeListener): void {
266    this.listener = listener;
267  }
268
269  public unregisterDataChangeListener(): void {
270    this.listener = null;
271  }
272}
273
274class Params {
275  item: string = '';
276
277  constructor(item: string) {
278    this.item = item;
279  }
280}
281
282@Builder
283function buildNode(param: Params = new Params("hello")) {
284  Row() {
285    Text(`C${param.item} -- `)
286    ReusableChildComponent2({ item: param.item }) //该自定义组件在ComponentContent中无法被正确复用
287  }
288}
289
290// 被回收复用的自定义组件,其状态变量会更新,而子自定义组件ReusableChildComponent3中的状态变量也会更新,但ComponentContent会阻断这一传递过程
291@Reusable
292@Component
293struct ReusableChildComponent {
294  @Prop item: string = '';
295  @Prop switch: string = '';
296  private content: NodeContent = new NodeContent();
297  private componentContent: ComponentContent<Params> = new ComponentContent<Params>(
298    this.getUIContext(),
299    wrapBuilder<[Params]>(buildNode),
300    new Params(this.item),
301    { nestingBuilderSupported: true });
302
303  aboutToAppear() {
304    let column = typeNode.createNode(this.getUIContext(), "Column");
305    column.initialize();
306    column.addComponentContent(this.componentContent);
307    this.content.addFrameNode(column);
308  }
309
310  aboutToRecycle(): void {
311    console.info(`${TEST_TAG} ReusableChildComponent aboutToRecycle ${this.item}`);
312
313    // 当开关为open,通过ComponentContent的reuse接口和recycle接口传递给其下的自定义组件,例如ReusableChildComponent2,完成复用
314    if (this.switch === 'open') {
315      this.componentContent.recycle();
316    }
317  }
318
319  aboutToReuse(params: object): void {
320    console.info(`${TEST_TAG} ReusableChildComponent aboutToReuse ${JSON.stringify(params)}`);
321
322    // 当开关为open,通过ComponentContent的reuse接口和recycle接口传递给其下的自定义组件,例如ReusableChildComponent2,完成复用
323    if (this.switch === 'open') {
324      this.componentContent.reuse(params);
325    }
326  }
327
328  build() {
329    Row() {
330      Text(`A${this.item}--`)
331      ReusableChildComponent3({ item: this.item })
332      ContentSlot(this.content)
333    }
334  }
335}
336
337@Component
338struct ReusableChildComponent2 {
339  @Prop item: string = "false";
340
341  aboutToReuse(params: Record<string, object>) {
342    console.info(`${TEST_TAG} ReusableChildComponent2 aboutToReuse ${JSON.stringify(params)}`);
343  }
344
345  aboutToRecycle(): void {
346    console.info(`${TEST_TAG} ReusableChildComponent2 aboutToRecycle ${this.item}`);
347  }
348
349  build() {
350    Row() {
351      Text(`D${this.item}`)
352        .fontSize(20)
353        .backgroundColor(Color.Yellow)
354        .margin({ left: 10 })
355    }.margin({ left: 10, right: 10 })
356  }
357}
358
359@Component
360struct ReusableChildComponent3 {
361  @Prop item: string = "false";
362
363  aboutToReuse(params: Record<string, object>) {
364    console.info(`${TEST_TAG} ReusableChildComponent3 aboutToReuse ${JSON.stringify(params)}`);
365  }
366
367  aboutToRecycle(): void {
368    console.info(`${TEST_TAG} ReusableChildComponent3 aboutToRecycle ${this.item}`);
369  }
370
371  build() {
372    Row() {
373      Text(`B${this.item}`)
374        .fontSize(20)
375        .backgroundColor(Color.Yellow)
376        .margin({ left: 10 })
377    }.margin({ left: 10, right: 10 })
378  }
379}
380
381
382@Entry
383@Component
384struct Index {
385  @State data: MyDataSource = new MyDataSource();
386
387  aboutToAppear() {
388    for (let i = 0; i < 100; i++) {
389      this.data.pushData(i.toString());
390    }
391  }
392
393  build() {
394    Column() {
395      List({ space: 3 }) {
396        LazyForEach(this.data, (item: string) => {
397          ListItem() {
398            ReusableChildComponent({
399              item: item,
400              switch: 'open' // 将open改为close可观察到,ComponentContent不通过reuse和recycle接口传递复用时,ComponentContent内部的自定义组件的行为表现
401            })
402          }
403        }, (item: string) => item)
404      }
405      .width('100%')
406      .height('100%')
407    }
408  }
409}
410```
411
412### dispose
413
414dispose(): void
415
416立即释放当前ComponentContent对象对[基本概念:实体节点](../../ui/arkts-user-defined-node.md#基本概念)的引用关系。关于ComponentContent的解绑场景请参见[解除实体节点引用关系](../../ui/arkts-user-defined-arktsNode-builderNode.md#解除实体节点引用关系)。
417
418**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
419
420**系统能力:** SystemCapability.ArkUI.ArkUI.Full
421
422> **说明:**
423>
424> 当ComponentContent对象调用dispose之后,会与后端实体节点解除引用关系。若前端对象ComponentContent无法释放,容易导致内存泄漏。建议在不再需要操作该ComponentContent对象时,开发者主动调用dispose释放后端节点,以减少引用关系的复杂性,降低内存泄漏的风险。
425
426**示例:**
427
428```ts
429import { BusinessError } from '@kit.BasicServicesKit';
430import { ComponentContent } from '@kit.ArkUI';
431
432class Params {
433  text: string = "";
434  constructor(text: string) {
435    this.text = text;
436  }
437}
438
439@Builder
440function buildText(params: Params) {
441  Column() {
442    Text(params.text)
443      .fontSize(50)
444      .fontWeight(FontWeight.Bold)
445      .margin({ bottom: 36 })
446  }.backgroundColor('#FFF0F0F0')
447}
448
449@Entry
450@Component
451struct Index {
452  @State message: string = "hello";
453
454  build() {
455    Row() {
456      Column() {
457        Button("click me")
458            .onClick(() => {
459                let uiContext = this.getUIContext();
460                let promptAction = uiContext.getPromptAction();
461                let contentNode = new ComponentContent(uiContext, wrapBuilder(buildText), new Params(this.message));
462                promptAction.openCustomDialog(contentNode);
463
464                setTimeout(() => {
465                  promptAction.closeCustomDialog(contentNode)
466                    .then(() => {
467                      console.info('customDialog closed.');
468                      if (contentNode !== null) {
469                        contentNode.dispose();   //释放contentNode
470                      }
471                    }).catch((error: BusinessError) => {
472                      let message = (error as BusinessError).message;
473                      let code = (error as BusinessError).code;
474                      console.error(`closeCustomDialog args error code is ${code}, message is ${message}`);
475                    })
476                }, 2000);     //2秒后自动关闭
477            })
478      }
479      .width('100%')
480      .height('100%')
481    }
482    .height('100%')
483  }
484}
485```
486
487
488### updateConfiguration
489
490updateConfiguration(): void
491
492传递[系统环境变化](../apis-ability-kit/js-apis-app-ability-configuration.md)事件,触发节点的全量更新。
493
494**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
495
496**系统能力:** SystemCapability.ArkUI.ArkUI.Full
497
498> **说明:**
499>
500> updateConfiguration接口用于通知对象更新当前的系统环境变化。
501
502**示例:**
503```ts
504import { NodeController, FrameNode, ComponentContent, UIContext, FrameCallback } from '@kit.ArkUI';
505import { AbilityConstant, Configuration, EnvironmentCallback, ConfigurationConstant } from '@kit.AbilityKit';
506
507@Builder
508function buildText() {
509  Column() {
510    Text('Hello')
511      .fontSize(36)
512      .fontWeight(FontWeight.Bold)
513  }
514  .backgroundColor($r('sys.color.ohos_id_color_background'))
515  .width('100%')
516  .alignItems(HorizontalAlign.Center)
517  .padding(16)
518}
519
520const componentContentMap: Array<ComponentContent<[Object]>> = new Array();
521
522class MyNodeController extends NodeController {
523  private rootNode: FrameNode | null = null;
524
525  makeNode(uiContext: UIContext): FrameNode | null {
526    return this.rootNode;
527  }
528
529  createNode(context: UIContext) {
530    this.rootNode = new FrameNode(context);
531    let component = new ComponentContent<Object>(context, wrapBuilder(buildText));
532    componentContentMap.push(component);
533    this.rootNode.addComponentContent(component);
534  }
535
536  deleteNode() {
537    let node = componentContentMap.pop();
538    this.rootNode?.dispose();
539    node?.dispose();
540  }
541}
542
543class MyFrameCallback extends FrameCallback {
544  onFrame() {
545    updateColorMode();
546  }
547}
548
549function updateColorMode() {
550  componentContentMap.forEach((value, index) => {
551    value.updateConfiguration();
552  })
553}
554
555@Entry
556@Component
557struct FrameNodeTypeTest {
558  private myNodeController: MyNodeController = new MyNodeController();
559
560  aboutToAppear(): void {
561    let environmentCallback: EnvironmentCallback = {
562      onMemoryLevel: (level: AbilityConstant.MemoryLevel): void => {
563        console.info('onMemoryLevel');
564      },
565      onConfigurationUpdated: (config: Configuration): void => {
566        console.info(`onConfigurationUpdated ${config}`);
567        this.getUIContext()?.postFrameCallback(new MyFrameCallback());
568      }
569    }
570    // 注册监听回调
571    this.getUIContext().getHostContext()?.getApplicationContext().on('environment', environmentCallback);
572    // 设置应用深浅色跟随系统
573    this.getUIContext()
574      .getHostContext()?.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
575    this.myNodeController.createNode(this.getUIContext());
576  }
577
578  aboutToDisappear(): void {
579    //移除map中的引用,并将自定义节点释放
580    this.myNodeController.deleteNode();
581  }
582
583  build() {
584    Column({ space: 16 }) {
585      NodeContainer(this.myNodeController);
586      Button('切换深色')
587        .onClick(() => {
588          this.getUIContext()
589            .getHostContext()?.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_DARK);
590        })
591      Button('设置浅色')
592        .onClick(() => {
593          this.getUIContext()
594            .getHostContext()?.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT);
595        })
596    }
597  }
598}
599```
600
601### isDisposed<sup>20+</sup>
602
603isDisposed(): boolean
604
605查询当前ComponentContent对象是否已解除与后端实体节点的引用关系。前端节点均绑定有相应的后端实体节点,当节点调用dispose接口解除绑定后,再次调用接口可能会出现crash、返回默认值的情况。由于业务需求,可能存在节点在dispose后仍被调用接口的情况。为此,提供此接口以供开发者在操作节点前检查其有效性,避免潜在风险。
606
607
608**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。
609
610**系统能力:** SystemCapability.ArkUI.ArkUI.Full
611
612**返回值:**
613
614| 类型    | 说明               |
615| ------- | ------------------ |
616| boolean | 后端实体节点是否解除引用。true为节点已与后端实体节点解除引用,false为节点未与后端实体节点解除引用。
617
618**示例:**
619
620```ts
621import { BusinessError } from '@kit.BasicServicesKit';
622import { ComponentContent } from '@kit.ArkUI';
623
624class Params {
625  text: string = "";
626  constructor(text: string) {
627    this.text = text;
628  }
629}
630
631@Builder
632function buildText(params: Params) {
633  Column() {
634    Text(params.text)
635      .fontSize(50)
636      .fontWeight(FontWeight.Bold)
637      .margin({ bottom: 36 })
638  }.backgroundColor('#FFF0F0F0')
639}
640
641@Entry
642@Component
643struct Index {
644  @State message: string = "hello";
645  @State beforeDispose: string = ''
646  @State afterDispose: string = ''
647
648  build() {
649    Row() {
650      Column() {
651        Button("click me")
652          .onClick(() => {
653            let uiContext = this.getUIContext();
654            let promptAction = uiContext.getPromptAction();
655            let contentNode = new ComponentContent(uiContext, wrapBuilder(buildText), new Params(this.message));
656            promptAction.openCustomDialog(contentNode);
657
658            setTimeout(() => {
659              promptAction.closeCustomDialog(contentNode)
660                .then(() => {
661                  console.info('customDialog closed.');
662                  if (contentNode !== null) {
663                    this.beforeDispose = contentNode.isDisposed() ? 'before dispose componentContent isDisposed is true' : 'before dispose componentContent isDisposed is false';
664                    contentNode.dispose();   //释放contentNode
665                    this.afterDispose = contentNode.isDisposed() ? 'after dispose componentContent isDisposed is true' : 'after dispose componentContent isDisposed is false';
666                  }
667                }).catch((error: BusinessError) => {
668                let message = (error as BusinessError).message;
669                let code = (error as BusinessError).code;
670                console.error(`closeCustomDialog args error code is ${code}, message is ${message}`);
671              })
672            }, 1000);     //1秒后自动关闭
673          })
674        Text(this.beforeDispose)
675          .fontSize(25)
676          .margin({ top: 10, bottom: 10 })
677        Text(this.afterDispose)
678          .fontSize(25)
679      }
680      .width('100%')
681      .height('100%')
682    }
683    .height('100%')
684  }
685}
686```
687
688![](figures/component_content_isDisposed.gif)
689
690### inheritFreezeOptions<sup>20+</sup>
691
692inheritFreezeOptions(enabled: boolean): void
693
694查询当前ComponentContent对象是否设置为继承父组件中自定义组件的冻结策略。如果设置继承状态为false,则ComponentContent对象的冻结策略为false。在这种情况下,节点在不活跃状态下不会被冻结。
695
696
697**原子化服务API:** 从API version 20开始,该接口支持在原子化服务中使用。
698
699**系统能力:** SystemCapability.ArkUI.ArkUI.Full
700
701**参数:**
702
703| 参数名 | 类型   | 必填 | 说明                                                                     |
704| ------ | ------ | ---- | ------------------------------------------------------------------------ |
705| enabled  | boolean | 是  | ComponentContent对象是否设置为继承父组件中自定义组件的冻结策略。true为继承父组件中自定义组件的冻结策略,false为不继承父组件中自定义组件的冻结策略。 |
706
707**示例:**
708
709```ts
710
711import { ComponentContent, FrameNode, NodeController } from '@kit.ArkUI';
712
713class Params {
714  count: number = 0;
715
716  constructor(count: number) {
717    this.count = count;
718  }
719}
720
721@Builder // builder组件
722function buildText(params: Params) {
723
724  Column() {
725    TextBuilder({ message: params.count })
726  }
727}
728
729class TextNodeController extends NodeController {
730  private rootNode: FrameNode | null = null;
731  private contentNode: ComponentContent<Params> | null = null;
732  private count: number = 0;
733
734  makeNode(context: UIContext): FrameNode | null {
735    this.rootNode = new FrameNode(context);
736    this.contentNode = new ComponentContent(context, wrapBuilder(buildText), new Params(this.count)); // 通过buildText创建ComponentContent
737    this.contentNode.inheritFreezeOptions(true); // 设置ComponentContent的冻结继承状态为True
738    if (this.rootNode !== null) {
739      this.rootNode.addComponentContent(this.contentNode); // 将ComponentContent上树
740    }
741    return this.rootNode;
742  }
743
744  update(): void {
745    if (this.contentNode !== null) {
746      this.count += 1;
747      this.contentNode.update(new Params(this.count)); // 更新ComponentContent中的数据,可以触发Log
748    }
749  }
750}
751
752const textNodeController: TextNodeController = new TextNodeController();
753
754@Entry
755@Component
756struct MyNavigationTestStack {
757  @Provide('pageInfo') pageInfo: NavPathStack = new NavPathStack();
758  @State message: number = 0;
759  @State logNumber: number = 0;
760
761  @Builder
762  PageMap(name: string) {
763    if (name === 'pageOne') {
764      pageOneStack({ message: this.message, logNumber: this.logNumber })
765    } else if (name === 'pageTwo') {
766      pageTwoStack({ message: this.message, logNumber: this.logNumber })
767    }
768  }
769
770  build() {
771    Column() {
772      Button('update ComponentContent') // 点击更新ComponentContent
773        .onClick(() => {
774          textNodeController.update();
775        })
776      Navigation(this.pageInfo) {
777        Column() {
778          Button('Next Page', { stateEffect: true, type: ButtonType.Capsule })
779            .width('80%')
780            .height(40)
781            .margin(20)
782            .onClick(() => {
783              this.pageInfo.pushPath({ name: 'pageOne' }); // 将name指定的NavDestination页面信息入栈
784            })
785        }
786      }.title('NavIndex')
787      .navDestination(this.PageMap)
788      .mode(NavigationMode.Stack)
789    }
790  }
791}
792
793@Component
794struct pageOneStack { // 页面一
795  @Consume('pageInfo') pageInfo: NavPathStack;
796  @State index: number = 1;
797  @Link message: number;
798  @Link logNumber: number;
799
800  build() {
801    NavDestination() {
802      Column() {
803        NavigationContentMsgStack({ message: this.message, index: this.index, logNumber: this.logNumber })
804        Button('Next Page', { stateEffect: true, type: ButtonType.Capsule }) // 切换至页面二
805          .width('80%')
806          .height(40)
807          .margin(20)
808          .onClick(() => {
809            this.pageInfo.pushPathByName('pageTwo', null);
810          })
811        Button('Back Page', { stateEffect: true, type: ButtonType.Capsule }) // 返回主页面
812          .width('80%')
813          .height(40)
814          .margin(20)
815          .onClick(() => {
816            this.pageInfo.pop();
817          })
818      }.width('100%').height('100%')
819    }.title('pageOne')
820    .onBackPressed(() => {
821      this.pageInfo.pop();
822      return true;
823    })
824  }
825}
826
827@Component
828struct pageTwoStack { // 页面二
829  @Consume('pageInfo') pageInfo: NavPathStack;
830  @State index: number = 2;
831  @Link message: number;
832  @Link logNumber: number;
833
834  build() {
835    NavDestination() {
836      Column() {
837        NavigationContentMsgStack({ message: this.message, index: this.index, logNumber: this.logNumber })
838        Text('BuilderNode处于冻结')
839          .fontWeight(FontWeight.Bold)
840          .margin({ top: 48, bottom: 48 })
841        Button('Back Page', { stateEffect: true, type: ButtonType.Capsule }) // 返回至页面一
842          .width('80%')
843          .height(40)
844          .margin(20)
845          .onClick(() => {
846            this.pageInfo.pop();
847          })
848      }.width('100%').height('100%')
849    }.title('pageTwo')
850    .onBackPressed(() => {
851      this.pageInfo.pop();
852      return true;
853    })
854  }
855}
856
857@Component({ freezeWhenInactive: true }) // 设置冻结策略为不活跃冻结
858struct NavigationContentMsgStack {
859  @Link message: number;
860  @Link index: number;
861  @Link logNumber: number;
862
863  build() {
864    Column() {
865      if (this.index === 1) {
866        NodeContainer(textNodeController)
867      }
868    }
869  }
870}
871
872@Component({ freezeWhenInactive: true }) // 设置冻结策略为不活跃冻结
873struct TextBuilder {
874  @Prop @Watch("info") message: number = 0;
875
876  info() {
877    console.info(`freeze-test TextBuilder message callback ${this.message}`); // 根据message内容变化来打印日志来判断是否冻结
878  }
879
880  build() {
881    Row() {
882      Column() {
883        Text(`文本更新次数: ${this.message}`)
884          .fontWeight(FontWeight.Bold)
885          .margin({ top: 48, bottom: 48 })
886      }
887    }
888  }
889}
890```
891
892![](figures/component_content_inheritFreezeOptions.gif)
893