Question
Is the bidirectional synchronization syntax of system components compatible with deeply nested objects?
Short Answer
$$ Syntax: System Component Bidirectional Synchronization: $$ The $$ operator provides a reference to TS variables for system components, enabling synchronization between TS variables and the internal state of system components.
!! Syntax: Two-way Binding: In State Management V1, the $$ syntax is used to implement two-way binding for system components. In State Management V2, the!! syntax sugar is used to uniformly handle two-way binding.
ArkUI fully supports bidirectional synchronization of deeply nested objects, which can be achieved through the following two approaches:
Solution 1: $$ Syntax.
The outer object must be reactive data (declared using decorators such as @State, @Link, etc.).
Deeply nested object properties must exist at initialization to avoid undefined references.
Prefer using class instead of struct for deep binding to simplify data update logic.
import { Model } from '../model/Model';
@Entry
@Component
struct SyncPage {
@State message: string = 'Hello World';
@State obj: Model = new Model();
build() {
Column({ space: 20 }) {
Column() {
Text(this.message)
}
Column() {
TextInput({ text: $$this.obj.model3.model4 })
.placeholderColor(Color.Grey)
.placeholderFont({ size: 14, weight: 400 })
.caretColor(Color.Blue)
.width(300)
.onChange((value: string) => {
this.message = this.obj.model3.model4;
})
}
}.width('100%').height('100%').justifyContent(FlexAlign.Center)
}
}
Entity class:
interface ModelInterface {
model4: string;
}
export class Model {
model1: string = '';
model2: number = 0;
model3: ModelInterface = { model4: 'model4' };
}
Option 2:!! Grammar.
Class names are decorated with @ComponentV2.
Objects are modified with @ObservedV2, and variables are decorated with @Trace.
Deep object properties exist at initialization to avoid undefined references.
Example code is as follows:
import { Model, ModelIn, ModelInterface } from '../model/Model';
@Entry
@ComponentV2
struct LocalChangePage {
@Local count: number = 0;
@Local message: string = "Hello";
@Local flag: boolean = false;
@Local model: Model = new Model('model1', 10, new ModelInterface('model4'), new ModelIn(10));
build() {
Column() {
Text(`${this.count}`)
Text(`${this.message}`)
Text(`${this.flag}`)
Text(`${this.model.model6.model5}`)
Button("change Local")
.onClick(() => {
// When the @Local annotation is applied to a simple type, assignment to the variable can be observed.
this.count++;
this.message += " World";
this.flag = !this.flag;
this.model.model6.model5++;
})
}
}
}
Entity class:
@ObservedV2
export class ModelInterface {
@Trace
model4: string;
constructor(model4: string) {
this.model4 = model4;
}
}
@ObservedV2
export class ModelIn {
@Trace
model5: number;
constructor(model5: number) {
this.model5 = model5;
}
}
@ObservedV2
export class Model {
@Trace
model1: string = '';
@Trace
model2: number = 0;
@Trace
model3: ModelInterface = new ModelInterface('model4');
@Trace
model6: ModelIn = new ModelIn(10);
constructor(model1: string, model2: number, model3: ModelInterface, model6: ModelIn) {
this.model1 = model1;
this.model2 = model2;
this.model3 = model3;
this.model6 = model6;
}
}
Applicable Scenarios
This example supports API Version 19 Release and later versions.
This example supports HarmonyOS 5.1.1 Release SDK and later versions.
This example requires DevEco Studio 5.1.1 Release or later for compilation and running.
Top comments (0)