Class 模型 + 跨组件状态(@Observed)+ 网络请求封装 + 本地存储全部是鸿蒙 Next/Stage 模型标准写法
AppStorage是鸿蒙的全局状态池,相当于 “内存级全局变量”@Link用于组件订阅 AppStorage 中的数据,数据变化时组件自动刷新封装成类,统一管理全局用户的读写,符合 “单一职责” 原则局部组件内状态 → 用@State父子组件间状态 → 用跨页面 / 全局状态 → 用所有数据模型优先用 Class 封装,不要用普通对象(可封装业务方法,易维护)
·
Class 模型 + 跨组件状态(@Observed)+ 网络请求封装 + 本地存储全部是鸿蒙 Next/Stage 模型标准写法
0. 整体结构
model/
├─ User.ets # Class 模型
├─ UserService.ets # 网络请求封装
├─ UserStorage.ets # 本地存储封装
pages/
├─ Index.ets # 主页面
├─ UserCard.ets # 子组件(跨组件状态演示)
1. model/User.ets
Class + Interface + 可观察对象(跨组件刷新)
// 接口约束
export interface IUser {
id: number;
name: string;
age: number;
vipLevel: number;
}
// 跨组件状态必须加 @Observed
@Observed
export class User implements IUser {
id: number;
name: string;
age: number;
vipLevel: number;
constructor(id: number, name: string, age: number, vipLevel: number) {
this.id = id;
this.name = name;
this.age = age;
this.vipLevel = vipLevel;
}
// 业务方法
isAdult(): boolean {
return this.age >= 18;
}
isVip(): boolean {
return this.vipLevel > 0;
}
}
2. model/UserService.ets
Class 封装网络请求
import http from '@ohos.net.http';
import { User } from './User';
export class UserService {
// 模拟获取用户列表
static async getUserList(): Promise<User[]> {
return new Promise((resolve) => {
// 真实项目替换为接口地址
setTimeout(() => {
const data = [
new User(1, "张三", 20, 2),
new User(2, "李四", 16, 0),
new User(3, "王五", 25, 1)
];
resolve(data);
}, 500);
});
}
// 真实网络请求示例
static async fetchUserFromNet(): Promise<User> {
let httpRequest = http.createHttp();
let resp = await httpRequest.request(
"https://mock-api.example.com/user",
{ method: http.RequestMethod.GET }
);
let json = JSON.parse(resp.result.toString());
return new User(json.id, json.name, json.age, json.vipLevel);
}
}
3. model/UserStorage.ets
Class 封装本地存储(偏好设置)
import dataPreferences from '@ohos.data.preferences';
import { User } from './User';
const PREF_NAME = 'user_pref';
export class UserStorage {
// 保存用户
static async saveUser(user: User): Promise<void> {
let pref = await dataPreferences.getPreferences(this.PREF_NAME);
await pref.put('user', JSON.stringify(user));
await pref.flush();
}
// 读取用户
static async loadUser(): Promise<User | null> {
try {
let pref = await dataPreferences.getPreferences(this.PREF_NAME);
let str = await pref.get('user', '');
if (!str) return null;
let obj = JSON.parse(str);
return new User(obj.id, obj.name, obj.age, obj.vipLevel);
} catch (e) {
return null;
}
}
// 清除
static async clearUser(): Promise<void> {
let pref = await dataPreferences.getPreferences(this.PREF_NAME);
await pref.clear();
}
}
4. pages/UserCard.ets
子组件 + @ObjectLink 跨组件状态同步
import { User } from '../model/User';
@Component
struct UserCard {
// 跨组件共享对象,必须用 @ObjectLink
@ObjectLink user: User;
build() {
Column() {
Text(`姓名:${this.user.name}`)
Text(`年龄:${this.user.age}`)
Text(`VIP:${this.user.vipLevel}`)
.fontColor(this.user.isVip() ? Color.Green : Color.Grey)
Button("年龄 +1")
.onClick(() => {
// 修改后,主页面也会同步刷新!
this.user.age += 1;
})
}
.width('100%')
.backgroundColor(0xf8f8f8)
.padding(12)
.borderRadius(10);
}
}
export default UserCard;
5. pages/Index.ets
主页面整合所有功能
import { User } from '../model/User';
import { UserService } from '../model/UserService';
import { UserStorage } from '../model/UserStorage';
import UserCard from './UserCard';
@Entry
@Component
struct Index {
// 可观察对象,支持跨组件刷新
@State currentUser: User = new User(0, "加载中...", 0, 0);
@State userList: User[] = [];
async aboutToAppear() {
// 1. 从本地加载
let localUser = await UserStorage.loadUser();
if (localUser) {
this.currentUser = localUser;
}
// 2. 从网络加载列表
let list = await UserService.getUserList();
this.userList = list;
}
build() {
Column({ space: 12 }) {
Text("三合一实战")
.fontSize(26)
.fontWeight(FontWeight.Bold);
// 跨组件子组件
UserCard({ user: this.currentUser });
// 保存到本地
Button("保存当前用户到本地")
.onClick(async () => {
await UserStorage.saveUser(this.currentUser);
});
Divider().margin(10);
// 网络请求列表
List({ space: 8 }) {
ForEach(this.userList, (user) => {
ListItem() {
Column() {
Text(user.name)
Text(`年龄:${user.age}`)
Text(`成年:${user.isAdult()}`)
.fontColor(user.isAdult() ? Color.Green : Color.Red)
}
.width('100%')
.backgroundColor(0xf2f2f2)
.padding(10)
.borderRadius(8);
}
})
}
}
.padding(20)
.width('100%')
}
}
6. 这三个功能分别对应什么?
① Class + @Observed + @ObjectLink
- 实现跨组件共享状态
- 子组件改数据 → 主页面自动刷新
- 鸿蒙官方推荐的组件通信方案
② Class 封装网络请求
- 把接口逻辑统一放 Service
- 结构清晰、便于维护、统一处理异常
③ Class 封装本地存储
- 偏好设置、用户信息、配置都存在这
- 重启 App 依然存在
| 功能 | 作用 |
|---|---|
| AppStorage | 鸿蒙全局状态池,所有组件可读写,跨页面 / 跨组件共享 |
| PersistentStorage | 把 AppStorage 中的指定数据持久化到本地,APP 重启后数据不丢 |
| @Observed + @ObjectLink | 组件间对象级状态同步 |
| Class 模型 | 封装数据和业务逻辑,结合状态管理实现响应式 |
完整代码(新增 / 修改部分标红)
1. 新增:model/GlobalUserModel.ets(全局状态 + 持久化)
import { AppStorage, PersistentStorage } from '@ohos.data.storage';
import { User } from './User';
// 1. 初始化全局默认用户
const defaultGlobalUser = new User(999, "全局默认用户", 18, 3);
// 2. 将全局用户注册到 AppStorage(全局状态池)
AppStorage.setOrCreate('globalUser', defaultGlobalUser);
// 3. 将 globalUser 持久化到本地(APP重启不丢)
PersistentStorage.persistProp('globalUser', defaultGlobalUser);
// 4. 封装全局用户的读写方法(方便调用)
export class GlobalUserModel {
// 获取全局用户
static getGlobalUser(): User {
return AppStorage.get('globalUser') as User;
}
// 更新全局用户
static updateGlobalUser(user: User): void {
AppStorage.set('globalUser', user);
}
// 修改全局用户属性(响应式)
static updateGlobalUserProp(key: keyof User, value: any): void {
const user = this.getGlobalUser();
user[key] = value;
AppStorage.set('globalUser', user); // 触发全局刷新
}
// 清空全局用户
static clearGlobalUser(): void {
AppStorage.set('globalUser', defaultGlobalUser);
}
}
2. 修改:model/User.ets(支持持久化序列化)
// 接口约束
export interface IUser {
id: number;
name: string;
age: number;
vipLevel: number;
}
// 跨组件状态必须加 @Observed
@Observed
export class User implements IUser {
id: number;
name: string;
age: number;
vipLevel: number;
constructor(id: number, name: string, age: number, vipLevel: number) {
this.id = id;
this.name = name;
this.age = age;
this.vipLevel = vipLevel;
}
// 业务方法
isAdult(): boolean {
return this.age >= 18;
}
isVip(): boolean {
return this.vipLevel > 0;
}
// 🔴 新增:序列化方法(持久化必备)
toJSON() {
return {
id: this.id,
name: this.name,
age: this.age,
vipLevel: this.vipLevel
};
}
// 🔴 新增:反序列化方法(从本地/全局读取后还原为Class实例)
static fromJSON(json: any): User {
return new User(json.id, json.name, json.age, json.vipLevel);
}
}
3. 新增:pages/GlobalUserPage.ets(全局状态演示页面)
import { GlobalUserModel } from '../model/GlobalUserModel';
import { User } from '../model/User';
import { LocalStorage } from '@ohos.data.storage';
@Entry
@Component
struct GlobalUserPage {
// 🔴 从AppStorage订阅全局用户(响应式)
@Link globalUser: User = GlobalUserModel.getGlobalUser();
build() {
Column({ space: 12 }) {
Text("全局状态 + 持久化演示")
.fontSize(26)
.fontWeight(FontWeight.Bold);
// 展示全局用户信息
Text(`全局用户:${this.globalUser.name}`)
Text(`全局用户年龄:${this.globalUser.age}`)
Text(`VIP等级:${this.globalUser.vipLevel}`)
.fontColor(this.globalUser.isVip() ? Color.Gold : Color.Grey);
// 修改全局用户属性(所有页面同步刷新)
Button("全局用户年龄+1")
.onClick(() => {
GlobalUserModel.updateGlobalUserProp('age', this.globalUser.age + 1);
});
// 修改全局用户名称
Button("修改全局用户名称为'鸿蒙全局用户'")
.onClick(() => {
GlobalUserModel.updateGlobalUserProp('name', '鸿蒙全局用户');
});
// 重置全局用户
Button("重置全局用户")
.backgroundColor(Color.Red)
.onClick(() => {
GlobalUserModel.clearGlobalUser();
});
// 跳回主页面(验证跨页面同步)
Navigator({ target: 'pages/Index' }) {
Text("返回主页面查看全局状态同步")
.fontSize(16)
.fontColor(Color.Blue);
}
}
.padding(20)
.width('100%')
}
}
4. 修改:pages/Index.ets(集成全局状态 + 持久化)
import { User } from '../model/User';
import { UserService } from '../model/UserService';
import { UserStorage } from '../model/UserStorage';
import UserCard from './UserCard';
import { GlobalUserModel } from '../model/GlobalUserModel'; // 🔴 新增
@Entry
@Component
struct Index {
// 可观察对象,支持跨组件刷新
@State currentUser: User = new User(0, "加载中...", 0, 0);
@State userList: User[] = [];
// 🔴 订阅全局用户(和GlobalUserPage同步)
@Link globalUser: User = GlobalUserModel.getGlobalUser();
async aboutToAppear() {
// 1. 从本地加载
let localUser = await UserStorage.loadUser();
if (localUser) {
this.currentUser = localUser;
}
// 2. 从网络加载列表
let list = await UserService.getUserList();
this.userList = list;
}
build() {
Column({ space: 12 }) {
Text("三合一+全局状态+持久化实战")
.fontSize(26)
.fontWeight(FontWeight.Bold);
// 🔴 新增:展示全局用户信息(和GlobalUserPage同步)
Text(`【全局共享】${this.globalUser.name} (年龄:${this.globalUser.age})`)
.fontSize(18)
.backgroundColor(0xe0f7fa)
.padding(8)
.borderRadius(6);
// 跳转到全局用户页面
Navigator({ target: 'pages/GlobalUserPage' }) {
Text("进入全局用户页面")
.fontSize(16)
.fontColor(Color.Blue);
}
Divider().margin(10);
// 跨组件子组件
UserCard({ user: this.currentUser });
// 保存到本地
Button("保存当前用户到本地")
.onClick(async () => {
await UserStorage.saveUser(this.currentUser);
});
Divider().margin(10);
// 网络请求列表
List({ space: 8 }) {
ForEach(this.userList, (user) => {
ListItem() {
Column() {
Text(user.name)
Text(`年龄:${user.age}`)
Text(`成年:${user.isAdult()}`)
.fontColor(user.isAdult() ? Color.Green : Color.Red)
}
.width('100%')
.backgroundColor(0xf2f2f2)
.padding(10)
.borderRadius(8);
}
})
}
}
.padding(20)
.width('100%')
}
}
5. 补充:修改 model/UserStorage.ets(适配 Class 反序列化)
import dataPreferences from '@ohos.data.preferences';
import { User } from './User';
const PREF_NAME = 'user_pref';
export class UserStorage {
// 保存用户
static async saveUser(user: User): Promise<void> {
let pref = await dataPreferences.getPreferences(PREF_NAME);
await pref.put('user', JSON.stringify(user)); // 用toJSON序列化
await pref.flush();
}
// 读取用户(🔴 新增反序列化)
static async loadUser(): Promise<User | null> {
try {
let pref = await dataPreferences.getPreferences(PREF_NAME);
let str = await pref.get('user', '');
if (!str) return null;
let obj = JSON.parse(str);
return User.fromJSON(obj); // 还原为Class实例
} catch (e) {
return null;
}
}
// 清除
static async clearUser(): Promise<void> {
let pref = await dataPreferences.getPreferences(PREF_NAME);
await pref.clear();
}
}
关键功能演示步骤
- 全局状态同步:
- 打开 Index 页面,看到 “全局用户:全局默认用户(年龄:18)”
- 点击 “进入全局用户页面”,点击 “全局用户年龄 + 1”,返回 Index 页面 → 年龄变为 19(跨页面同步)
- 持久化验证:
- 在全局用户页面修改名称为 “鸿蒙全局用户”,关闭 APP 重启 → 名称依然是 “鸿蒙全局用户”(PersistentStorage 生效)
- 本地存储 + Class 反序列化:
- 保存 currentUser 到本地,重启 APP → 加载的是本地保存的用户(不是默认值)
核心知识点总结
1. AppStorage + @Link 全局状态
AppStorage是鸿蒙的全局状态池,相当于 “内存级全局变量”@Link用于组件订阅 AppStorage 中的数据,数据变化时组件自动刷新- 封装成
GlobalUserModel类,统一管理全局用户的读写,符合 “单一职责” 原则
2. PersistentStorage 持久化
- 把 AppStorage 中的指定 key(如
globalUser)持久化到本地 - Class 必须实现
toJSON/fromJSON方法,否则持久化后会丢失 Class 的方法(变成普通对象)
3. 完整的状态管理链路
Class模型(User)→ 本地存储(UserStorage)→ 全局状态(GlobalUserModel)→ 组件(@Link/@ObjectLink)→ UI自动刷新
最后:鸿蒙状态管理最佳实践
- 局部组件内状态 → 用
@State - 父子组件间状态 → 用
@Observed + @ObjectLink - 跨页面 / 全局状态 → 用
AppStorage + @Link + PersistentStorage - 所有数据模型优先用 Class 封装,不要用普通对象(可封装业务方法,易维护)
更多推荐




所有评论(0)