当前位置:首页>鸿蒙APP>鸿蒙开发-MVVM框架实战

鸿蒙开发-MVVM框架实战

  • 2026-11-09 15:35:26
鸿蒙开发-MVVM框架实战
MVVM作为主流的前端架构模式,在实际项目开发中是常用的框架,它实现UI与数据的优雅解耦,让代码变得清晰。本文分享鸿蒙MVVM框架的实战经验,基于以下开发环境:
开发工具:DevEco Studio 6.0 ReleaseAPI 版本:20

一、 MVVM 框架的简要理解

MVVM(Model、ViewModel、Model) 的核心是数据绑定,而数据绑定的底层实现,笔者认为几乎无一例外都可理解为基于观察者模式。
观察目标(Observable):当Model层的数据发生变化时,它会发出变化通知
观察者(Observer):视图(View)会监听所需关注的对象数据变化通知,一旦数据发生变化,视图就会重新刷新渲染对应数据的显示

二、鸿蒙 ArkTS MVVM实现

1.Model 层

本文仍然用登录界面来介绍,新建用户数据类:src/main/ets/model/UserModel.ets
@Observed  export class UserModel {    username: string = '';    password: string = '';    token: string = '';    isLoggedIn: boolean = false;    constructor(username: string = '', password: string = '') {      this.username = username;      this.password = password;    }  }

2.ViewModel 层

业务处理层,处理用户登录的业务逻辑:src/main/ets/viewmodel/LoginViewModel.ets
import { UserModel } from '../model/UserModel';  import userNapi, { LoginResult } from 'libuser_napi.so';  @Observed  export class LoginViewModel {    // 状态数据(驱动UI刷新)    user: UserModel = new UserModel();    isLoading: boolean = false;    errorMessage: string = '';    loginSuccess: boolean = false;    // 更新用户名    setUsername(value: string): void {      this.user.username = value;      this.errorMessage = '';    }    // 更新密码    setPassword(value: string): void {      this.user.password = value;      this.errorMessage = '';    }    // 登录验证    async login(): Promise<boolean> {      // 本地校验      if (!this.user.username.trim()) {        this.errorMessage = '请输入用户名';        return false;      }      if (!this.user.password.trim()) {        this.errorMessage = '请输入密码';        return false;      }      if (this.user.password.length < 6) {        this.errorMessage = '密码至少6位';        return false;      }      // 调用NAPI进行服务端验证(模拟)      this.isLoading = true;      this.errorMessage = '';      try {        // 调用C++层NAPI接口        const result: LoginResult = userNapi.login(this.user.username, this.user.password);        if (result.success) {          this.user.token = result.token;          this.user.isLoggedIn = true;          this.loginSuccess = true;          return true;        } else {          this.errorMessage = result.message || '登录失败';          return false;        }      } catch (error) {        this.errorMessage = '网络错误,请重试';        return false;      } finally {        this.isLoading = false;      }    }    // 退出登录    logout(): void {      this.user = new UserModel();      this.loginSuccess = false;      this.errorMessage = '';      // 调用C++层注销      //userNapi.logout();    }  }

3.  View 层

简单的登录界面: src/main/ets/view/LoginPage.ets
import { LoginViewModel } from '../viewmodel/LoginViewModel';  @Entry  @Component  struct LoginPage {    @State viewModel: LoginViewModel = new LoginViewModel();    build() {      Column({ space: 20 }) {        // 标题        Text('用户登录')          .fontSize(28)          .fontWeight(FontWeight.Bold)          .margin({ top: 100, bottom: 50 })        // 用户名输入        Column({ space: 8 }) {          Text('用户名')            .fontSize(14)            .fontColor('#666')            .alignSelf(ItemAlign.Start)          TextInput({ placeholder: '请输入用户名' ,            text: this.viewModel.user.username  // ← 关键!绑定 VM 值             })            .width('100%')            .height(48)            .backgroundColor('#F5F5F5')            .borderRadius(8)            .padding({ left: 16 })            .onChange((value: string) => {              this.viewModel.setUsername(value);            })        }        .width('80%')        // 密码输入        Column({ space: 8 }) {          Text('密码')            .fontSize(14)            .fontColor('#666')            .alignSelf(ItemAlign.Start)          TextInput({ placeholder: '请输入密码',            text: this.viewModel.user.password  // ← 关键!绑定 VM 值          })            .width('100%')            .height(48)            .backgroundColor('#F5F5F5')            .borderRadius(8)            .padding({ left: 16 })            .type(InputType.Password)  // 密码输入模式            .onChange((value: string) => {              this.viewModel.setPassword(value);            })        }        .width('80%')        // 错误提示        if (this.viewModel.errorMessage) {          Text(this.viewModel.errorMessage)            .fontSize(14)            .fontColor('#FF4444')            .margin({ top: 8 })        }        // 登录按钮        Button(this.viewModel.isLoading ? '登录中...' : '登 录')          .width('80%')          .height(50)          .backgroundColor(this.viewModel.isLoading ? '#CCCCCC' : '#007DFF')          .fontSize(16)          .fontColor(Color.White)          .borderRadius(8)          .margin({ top: 30 })          .enabled(!this.viewModel.isLoading)          .onClick(async () => {            const success = await this.viewModel.login();            if (success) {              // 登录成功,跳转到首页              console.info('登录成功,token:', this.viewModel.user.token);            }          })        // 登录成功提示        if (this.viewModel.loginSuccess) {          Column({ space: 10 }) {            Text('✓ 登录成功')              .fontSize(18)              .fontColor('#52C41A')            Text(`欢迎,${this.viewModel.user.username}`)              .fontSize(14)              .fontColor('#666')            Button('退出登录')              .width(120)              .height(40)              .backgroundColor('#FF4444')              .fontSize(14)              .onClick(() => {                this.viewModel.logout();              })          }          .margin({ top: 30 })          .padding(20)          .backgroundColor('#F6FFED')          .borderRadius(8)        }      }    .width('100%')      .height('100%')      .backgroundColor(Color.White)    }  }

三、 效果与总结

在执行logout()函数的时候,自动清空输入框中的用户和密码信息:
// 退出登录  logout(): void {    this.user = new UserModel();    this.loginSuccess = false;    this.errorMessage = '';    // 调用C++层注销    //userNapi.logout();  }
总结:MVVM的数据绑定主要是通过以下的方式实现:
使用@State装饰器,自动监听LoginViewModel对象的数据变化
@State viewModel: LoginViewModel = new LoginViewModel(); 
绑定控件与LoginViewModel的数据,当LoginViewModel对象中的数据发生变化时候,自动触发UI控件的重绘渲染
text: this.viewModel.user.username  
控件的值发生变化时,修改LoginViewModel中的值:
onChange((value: string) => {      this.viewModel.setUsername(value);  })
本文主要体现ArkTS的源码,native c++部分未展出,如有需要全工程者,请点赞加关注,留言。谢谢!

最新文章

随机文章