关键字一

@State + @Prop(单向同步):

不管父组件数据变化,关联数据都会变化,而且子组件的@Prop可以继续使用@Prop链接,但是此方法只能局限于纯粹的祖父子页面传递,且层级之间需要添加关联变量

  • 父组件通过 @State 管理数据,子组件通过 @Prop 接收数据;子组件修改数据‌不会‌反向同步父组件。

  • 父组件向子组件传递只读数据。

    // 父组件
    @State message: string = "Hello";
    Child({ message: this.message })
    
    // 子组件
    @Prop message: string; // 仅接收父数据
    

@State与@Link装饰器:

不管父子组件数据谁变化,关联数据都会变化,而且子组件的@Link可以继续使用@Link链接,但是此方法只能局限于纯粹的子父祖页面传递,且层级之间需要添加关联变量

  • @State: 组件内部的状态管理,状态变化会触发UI重新渲染。

  • @Link: 用于父子组件之间的双向数据绑定,需与父组件的@State或@Link变量关联。

    @Entry
    	@Component
    	struct StateExample {
    	  @State count: number = 0
    	
    	  build() {
    	    Column() {
    	      Text(`Count: ${this.count}`).fontSize(30)
    	      Button('Increase').onClick(() => {
    	        this.count += 1
    	      })
    	    }.width('100%').height('100%').justifyContent(FlexAlign.Center)
    	  }
    	}
    	// 点击按钮时,count值变化,Text组件自动更新显示。
    	// @State变量仅对当前组件有效。
    	 ```
    - @Link用于建立父子组件间的双向绑定,需从父组件传递@State或@Link变量。
    	```typescript 
    	// 子组件通过@Link接收父组件的@State变量(需用$符号传递引用)。
    	// 在子组件修改value会同步更新父组件的parentValue。
    	// 子组件
    	@Component
    	struct ChildComponent {
    	  @Link value: number
    	
    	  build() {
    	    Button(`Child Value: ${this.value}`)
    	      .onClick(() => {
    	        this.value += 1 // 修改会同步到父组件
    	      })
    	  }
    	}
    	
    	// 父组件
    	@Entry
    	@Component
    	struct ParentComponent {
    	  @State parentValue: number = 0
    	
    	  build() {
    	    Column() {
    	      Text(`Parent Value: ${this.parentValue}`).fontSize(30)
    	      ChildComponent({ value: $parentValue }) // 使用$传递@State引用
    	    }.width('100%').height('100%').justifyContent(FlexAlign.Center)
    	  }
    	}
    

@Observed + @ObjectLink‌

  • @State 装饰器只能监听对象的‌直接属性替换‌或‌第一层属性变化‌,无法检测嵌套对象内部属性的修改

  • @Observed‌:装饰‌自定义类‌,标记其实例属性可被观察(需在类定义前使用)

  • @ObjectLink‌:在子组件中装饰变量,接收 @Observed 类的实例,建立‌双向数据绑定

    @Observed 只能装饰类,不可单独用于变
    @ObjectLink 变量‌不可直接赋值‌(如 this.user = new User() 非法),只能修改属性

嵌套对象属性同步

  • 父组件通过 @State 管理 User 实例,子组件通过 @ObjectLink 绑定该实例
  • 修改 user.age (无论父子组件)均触发界面更新
    // 定义可观察类
    @Observed
    class User {
      name: string;
      age: number;
      constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
      }
    }
    
    // 父组件
    @Entry
    @Component
    struct ParentPage {
      @State user: User = new User('Alice', 25); // 状态管理
    
      build() {
        Column() {
          ChildComponent({ user: this.user }) // 传递对象
          Button('修改年龄').onClick(() => {
            this.user.age++; // 父组件修改属性
          })
        }
      }
    }
    
    // 子组件
    @Component
    struct ChildComponent {
      @ObjectLink user: User; // 双向绑定嵌套对象
    
      build() {
        Column() {
          Text(`年龄: ${this.user.age}`) // 自动更新
          Button('子组件修改').onClick(() => {
            this.user.age = 30; // 子组件修改同步到父组件
          })
        }
      }
    }
    

数组元素属性更新

  • 每个数组元素 TodoItem 被 @Observed 装饰,子组件通过 @ObjectLink 监听其属性变化

  • 切换开关时修改 item.completed 会同步更新 UI

    @Observed
    class TodoItem {
      id: number;
      text: string;
      completed: boolean = false;
      constructor(id: number, text: string) {
        this.id = id;
        this.text = text;
      }
    }
    
    @Entry
    @Component
    struct TodoList {
      @State todos: TodoItem[] = [
        new TodoItem(1, '买牛奶'),
        new TodoItem(2, '看书')
      ];
    
      build() {
        Column() {
          ForEach(this.todos, (item: TodoItem) => {
            TodoItemComponent({ item: item }) // 传递数组项
          })
        }
      }
    }
    
    @Component
    struct TodoItemComponent {
      @ObjectLink item: TodoItem; // 绑定数组元素
    
      build() {
        Row() {
          Text(this.item.text)
            .decoration({ type: this.item.completed ? TextDecorationType.LineThrough : TextDecorationType.None })
          Toggle()
            .isOn(this.item.completed)
            .onChange((checked: boolean) => {
              this.item.completed = checked; // 修改元素属性
            })
        }
      }
    }
    

@Param 单向输入

  • 父组件通过属性绑定传递数据,子组件用 @Param 接收,数据流为‌单向‌(父→子)

    // 父组件
    @ComponentV2
    struct Parent {
      @Local message: string = "Hello";
      build() {
        Child({ msg: this.message }) // 传递数据
      }
    }
    
    // 子组件
    @ComponentV2
    struct Child {
      @Param msg: string = ""; // 接收父组件数据
    }
    

@Provider + @Consumer‌

  • @Provider 提供数据,后代组件通过 @Consumer 绑定相同 key 实现双向同步

  • 仅支持 ComponentV2,数据类型需严格匹配

    // 父组件
    @ComponentV2
    struct Parent {
      @Provider('user') user: User = new User('Alice');
    }
    
    // 子组件
    @ComponentV2
    struct Child {
      @Consumer('user') user: User; // 双向绑定
    }
    

@Event 子传父通信

  • 子组件通过 @Event 定义回调函数,父组件重写该函数实现数据回传

    // 父组件
    @ComponentV2
    struct Parent {
      @Local title: string = "Title";
      build() {
        Child({ 
          onUpdate: (newTitle: string) => { this.title = newTitle; }
        })
      }
    }
    
    // 子组件
    @ComponentV2
    struct Child {
      @Event onUpdate: (title: string) => void;
      Button("更新标题").onClick(() => this.onUpdate("New Title"));
    }
    

@ObservedV2 + @Trace‌

  • 监听嵌套对象属性的深度变化,避免全对象刷新

    @ObservedV2
    class User {
      @Trace name: string; // 仅监听name变化
      age: number;
    }
    
    @ComponentV2
    struct Profile {
      @Local user: User = new User();
    }
    
特性‌ V1 (Component)‌ ‌V2 (ComponentV2)‌
双向同步‌ @Provide + @Consume @Provider + @Consumer
‌事件回调‌ 自定义事件 @Event 装饰器
‌深度监听‌ @Observed + @ObjectLink @ObservedV2 + @Trace
‌计算属性‌ @Computed

事件总线

EventHub

  • 通过事件发布/订阅模式实现解耦通信
  • 一对多广播、组件间松耦合交互
    import eventHub from '@ohos.events.eventHub';
    
    /*********************** 订阅事件 START *********************/
    eventHub.on('customEvent', (data) => {
      console.log('Received event data:', data);
    });
    
    // 异步处理
    eventHub.on('asyncEvent', async (data) => {
      await someAsyncOperation(data);
    });
    
    // 页面关闭时一定要:在组件销毁时及时取消订阅,防止内存泄漏。
    eventHub.off('customEvent', callbackFunc);
    /********************** 订阅事件 END ************************/
    
    /********************** 发布事件 START **********************/
    // 发布普通事件
    eventHub.emit('customEvent', { key: 'value' });
    
    // 粘性事件
    eventHub.emitSticky('stickyEvent', { stickyData: 'value' });
    /********************** 发布事件 END ************************/
    

全局状态管理

AppStorage或LocalStorage

  • 应用级全局存储,数据变化自动同步到所有依赖组件。

  • 多组件共享的全局状态(如用户信息、主题)。

    // 存储简单数据
    AppStorage.SetOrCreate('theme', 'dark');
    
    // 存储对象
    AppStorage.SetOrCreate('user', { name: 'Alice', age: 25 });
    
    // 直接读取
    let theme = AppStorage.Get('theme');
    
    // 在组件中响应式绑定
    @Entry
    @Component
    struct MyComponent {
      @StorageLink('theme') theme: string = 'light';
    
      build() {
        Text(`当前主题: ${this.theme}`)
      }
    }
    
    // 删除数据
    AppStorage.Delete('theme');
    
    // 对象类型监听
    const user = AppStorage.SetAndLink('user', { name: 'Bob', age: 30 });
    
    // 修改时会触发UI更新
    user.age = 31;
    

观察者模式

当其他组件操作数据时,观察者能根据数据变化做出回应

官网链接

createIntersectionObserver + observe + unobserve


// 导入API
import { IntersectionObserver } from '@ohos.intersectionobserver';

@Entry
@Component
struct VisibilityMonitor {
  private observer: IntersectionObserver | null = null;
  @State isVisible: boolean = false;
  @State viewRatio: number = 0;

  aboutToAppear() {
    // 1. 创建观察者
    this.observer = new IntersectionObserver();
    
    // 2. 设置观察回调
    this.observer.observe(this.$('targetView'), (isVisible: boolean, ratio: number) => {
      this.isVisible = isVisible;
      this.viewRatio = ratio;
      console.log(`可见状态: ${isVisible}, 显示比例: ${ratio}`);
    });
  }

  aboutToDisappear() {
    // 3. 停止观察
    this.observer?.unobserve(this.$('targetView'));
    this.observer = null;
  }

  build() {
    Column() {
      // 被观察的目标组件
      Text('Target View')
        .width(200)
        .height(200)
        .backgroundColor(this.isVisible ? Color.Green : Color.Red)
        .margin(20)
        .id('targetView')

      // 显示观察结果
      Text(`可见: ${this.isVisible ? '是' : '否'}`)
      Text(`显示比例: ${this.viewRatio.toFixed(2)}`)
    }
  }
}
@Component
struct ObserverExample {
  private observer: IntersectionObserver | null = null;

  aboutToAppear() {
    // 创建并配置观察者
    this.observer = this.createIntersectionObserver({
      thresholds: [0.2, 0.5, 1.0],
      observeAll: false
    });

    // 绑定观察回调
    this.observer.observe('.scroll-view-item', (res) => {
      console.log(`当前可见比例: ${res.intersectionRatio}`);
    });
  }

  aboutToDisappear() {
    // 组件销毁时解除观察
    if (this.observer) {
      this.observer.unobserve('.scroll-view-item');
      this.observer = null;
    }
  }

  build() {
    Column() {
      Scroll() {
        ForEach([1, 2, 3, 4, 5], (item) => {
          Text(`Item ${item}`)
            .height(200)
            .width('100%')
            .backgroundColor(Color.Gray)
            .class('scroll-view-item')
        })
      }
    }
  }
}

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐