Skip to content

状态管理

概述

HCompass 强制使用 V2 版本的状态管理 API,确保代码的一致性和可维护性。

V2 状态管理 API

@ObservedV2

用于标记可观察的类:

typescript
@ObservedV2
export class MyViewModel {
  @Trace count: number = 0;
}

@Trace

用于标记需要追踪的属性:

typescript
@ObservedV2
export class MyViewModel {
  @Trace count: number = 0;
  @Trace name: string = "";
  @Trace isLoading: boolean = false;
}

@Local

用于在组件中引用状态:

typescript
@Entry
@Component
struct MyPage {
  @Local viewModel: MyViewModel = new MyViewModel();

  build() {
    Column() {
      Text(`${this.viewModel.count}`);
      Button("增加")
        .onClick(() => {
          this.viewModel.count++;
        });
    }
  }
}

状态管理层次

1. 组件级状态

仅在单个组件内使用的状态:

typescript
@Entry
@Component
struct MyPage {
  @State count: number = 0;

  build() {
    Column() {
      Text(`${this.count}`);
      Button("增加")
        .onClick(() => {
          this.count++;
        });
    }
  }
}

2. ViewModel 状态

跨组件共享的状态,封装在 ViewModel 中:

typescript
@ObservedV2
export class MyViewModel {
  @Trace count: number = 0;

  increment(): void {
    this.count++;
  }
}

@Entry
@Component
struct MyPage {
  @Local viewModel: MyViewModel = new MyViewModel();

  build() {
    Column() {
      Text(`${this.viewModel.count}`);
      Button("增加")
        .onClick(() => {
          this.viewModel.increment();
        });
    }
  }
}

3. 全局状态

跨功能包共享的状态,使用 AppStorageV2:

typescript
@ObservedV2
export class AppState {
  @Trace isLoggedIn: boolean = false;
  @Trace currentUser: UserInfo | null = null;

  static getInstance(): AppState {
    return AppStorageV2.getOrCreate("AppState", () => new AppState());
  }
}

// 使用
const appState = AppState.getInstance();
appState.isLoggedIn = true;

状态更新

直接赋值

typescript
@ObservedV2
export class MyViewModel {
  @Trace count: number = 0;

  increment(): void {
    this.count++;  // 直接赋值,自动触发 UI 更新
  }
}

对象更新

typescript
@ObservedV2
export class MyViewModel {
  @Trace userInfo: UserInfo | null = null;

  updateUserInfo(info: UserInfo): void {
    // 创建新对象,而不是修改原对象
    this.userInfo = { ...info };
  }
}

数组更新

typescript
@ObservedV2
export class MyViewModel {
  @Trace dataList: Item[] = [];

  addItem(item: Item): void {
    // 创建新数组,而不是修改原数组
    this.dataList = [...this.dataList, item];
  }

  removeItem(index: number): void {
    this.dataList = this.dataList.filter((_, i) => i !== index);
  }
}

最佳实践

1. 使用 V2 API

强制使用 V2 版本的状态管理 API:

typescript
// 推荐
@ObservedV2
export class MyViewModel {
  @Trace count: number = 0;
}

// 禁止
@Observed
export class MyViewModel {
  @Track count: number = 0;
}

2. 不可变性

始终创建新对象,而不是修改原对象:

typescript
// 推荐
this.userInfo = { ...this.userInfo, name: "新名字" };

// 禁止
this.userInfo.name = "新名字";

3. 状态封装

将状态封装在 ViewModel 中,而不是直接在 View 中管理:

typescript
// 推荐
@ObservedV2
export class MyViewModel {
  @Trace count: number = 0;

  increment(): void {
    this.count++;
  }
}

// 不推荐
@Entry
@Component
struct MyPage {
  @State count: number = 0;

  build() {
    Column() {
      Button("增加")
        .onClick(() => {
          this.count++;  // 业务逻辑不应该在 View 中
        });
    }
  }
}

4. 避免过度使用全局状态

只将真正需要跨功能包共享的状态放在全局:

typescript
// 推荐:全局状态
@ObservedV2
export class AppState {
  @Trace isLoggedIn: boolean = false;
  @Trace currentTheme: string = "light";
}

// 不推荐:局部状态放在全局
@ObservedV2
export class AppState {
  @Trace userProfilePageScrollPosition: number = 0;  // 这应该是局部状态
}

性能优化

1. 避免频繁更新

typescript
// 不推荐
for (let i = 0; i < 1000; i++) {
  this.count++;  // 每次都会触发 UI 更新
}

// 推荐
let newCount = this.count;
for (let i = 0; i < 1000; i++) {
  newCount++;
}
this.count = newCount;  // 只触发一次 UI 更新

2. 使用计算属性

typescript
@ObservedV2
export class MyViewModel {
  @Trace firstName: string = "";
  @Trace lastName: string = "";

  get fullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
}

注意事项

  1. V2 API:强制使用 V2 版本的状态管理 API
  2. 不可变性:始终创建新对象,不修改原对象
  3. 性能优化:避免频繁更新状态

下一步