鸿蒙状态管理的V1与V2区别

      最近终于把项目升级到了鸿蒙的最新版本,其中最大的感受就是——状态管理V2版本真香!不过,在说V2之前,得先回顾一下V1的那些事。

一、V1版本的装饰器:简单但有限

        在V1版本里,鸿蒙的状态管理主要依靠几个核心的装饰器,比如@State@Prop@Link@Provide/@Consume@Observed等。它们虽然能满足基本的开发需求,但在一些复杂场景下就显得有些力不从心了。

  • @State:用于声明组件的状态变量,但跨组件共享状态不够方便。

V1代码示例

// 组件A
@State countA: number = 0;

// 组件B(子组件)
@Consume countConsume: number = this.countA; // 需要通过@Provide和@Consume共享状态
  • @Prop:用于父子组件传值,但只能单向传递。

V1代码示例

// 父组件
@State title: string = '标题';

// 子组件
@Prop titleProp: string = this.title; // 子组件无法直接修改titleProp
  • @Link:用于连接父子组件的状态,但实现方式较为繁琐。

V1代码示例

// 父组件
@State parentCount: number = 0;

// 子组件
@Link(from: 'parentCount', to: 'childCount')
@State childCount: number = 0; // 需要通过@Link连接父子组件状态
  • @Provide@Consume:用于跨组件共享状态,但层级较深时维护起来比较麻烦。

V1代码示例

// 祖先组件
@Provide sharedState: { data: string } = { data: '共享数据' };

// 后代组件
@Consume sharedStateConsume: { data: string } = this.sharedState; // 后代组件消费状态
  • @Observed:用于观测对象的变化,但观测深度有限。

V1代码示例

@Observed user: { name: string; address: { city: string } } = { name: '张三', address: { city: '北京' } };

// 修改嵌套对象的属性,有时界面不会自动更新
this.user.address.city = '上海'; // 可能不会触发界面更新

二、V2版本的装饰器:全面升级,更加强大

        升级到V2版本后,鸿蒙的状态管理进行了全面的升级和优化。不仅保留了V1版本的核心装饰器,还引入了一些新的特性和改进。

@State:状态管理更便捷

在V2版本里,@State装饰器得到了加强,不仅支持组件内部的状态管理,还支持跨组件共享状态。

// 组件A
@State countA: number = 0; // 声明一个状态变量countA

// 组件B(子组件)
@Consume countConsume: number = this.countA; // 直接消费组件A的countA,无需@Provide
  • @Prop:父子传值更灵活

V2版本的@Prop装饰器支持双向绑定和单向绑定两种模式。

// 父组件
@State title: string = '默认标题';

// 子组件
@Prop(sync: true) titleProp: string = this.title; // 支持双向绑定

// 子组件中修改titleProp的值
this.titleProp = '新的标题'; // 父组件的title也会同步更新
  • @Link:状态连接更直观

V2版本的@Link装饰器实现方式更加直观。

// 父组件
@State parentCount: number = 0;

// 子组件
@Link(from: 'parentCount', to: 'childCount')
@State childCount: number = 0; // 更直观的连接父子组件状态
  • @Provide和@Consume:状态共享更高效

V2版本的@Provide@Consume装饰器支持任意组件之间的状态共享。

// 任意组件A
@Provide sharedState: { data: string } = { data: '共享数据' };

// 任意组件B
@Consume sharedStateConsume: { data: string } = this.sharedState; // 任意组件都可以消费状态
  • @Observed:对象观测更全面

V2版本的@Observed装饰器观测深度更深。

@Observed user: { name: string; address: { city: string } } = { name: '张三', address: { city: '北京' } };

// 修改嵌套对象的属性,界面会自动更新
this.user.address.city = '上海'; // 界面会自动更新

总的来说,鸿蒙状态管理V2版本在V1版本的基础上进行了全面的升级和优化。特别是@State@Prop@Link@Provide/@Consume以及@Observed这些装饰器的改进,让状态管理变得更加便捷、灵活和高效。

        继续,聊聊那些可能被忽略,但却非常实用的装饰器们。

        在V1版本里,除了之前提到的那些核心装饰器外,还有一些装饰器虽然不那么显眼,但在特定场景下却能发挥大作用。

  • @local:用于声明局部变量,避免与全局状态冲突。

    V1代码示例

    @Entry
    struct MyComponent {
      @State globalCount: number = 0;
    
      build() {
        Column() {
          // 使用@local声明局部变量,避免与全局状态冲突
          @local localCount: number = 0;
    
          Button('增加全局计数')
            .onClick(() => {
              this.globalCount++;
            })
          Button('增加局部计数')
            .onClick(() => {
              localCount++; // 操作的是局部变量,不会影响全局状态
            })
          Text(`全局计数:${this.globalCount},局部计数:${localCount}`)
        }
      }
    }
  • @param:用于声明函数参数,提高代码可读性。

    V1代码示例

    function addNumbers(@param a: number, @param b: number): number {
      return a + b;
    }
    
    // 调用函数时,参数名会作为提示显示
    let result = addNumbers(2, 3);
  • @once:用于声明只执行一次的函数,避免重复执行。

    V1代码示例

    @Entry
    struct MyComponent {
      @State count: number = 0;
    
      @once
      init() {
        console.log('初始化函数只执行一次');
        this.count = 10;
      }
    
      build() {
        Column() {
          Button('增加计数')
            .onClick(() => {
              this.count++;
              this.init(); // 即使多次点击,init函数也只执行一次
            })
          Text(`计数:${this.count}`)
        }
      }
    }
  • @Event:用于声明自定义事件,实现组件间通信。

    V1代码示例

    // 子组件
    @Entry
    struct ChildComponent {
      @Event onButtonClick: () => void;
    
      build() {
        Button('点击我')
          .onClick(() => {
            this.onButtonClick(); // 触发自定义事件
          })
      }
    }
    
    // 父组件
    @Entry
    struct ParentComponent {
      build() {
        Column() {
          ChildComponent()
            .onButtonClick(() => {
              console.log('按钮被点击了'); // 父组件监听子组件的自定义事件
            })
        }
      }
    }
  • @monitor:用于监听对象的变化,实现深度观测。

    V1代码示例

    @Entry
    struct MyComponent {
      @State user: { name: string; age: number } = { name: '张三', age: 20 };
    
      @monitor
      onUserChange(newValue: { name: string; age: number }, oldValue: { name: string; age: number }) {
        console.log('用户信息发生变化:', newValue, oldValue);
      }
    
      build() {
        Column() {
          Button('修改用户信息')
            .onClick(() => {
              this.user = { name: '李四', age: 25 }; // 修改用户信息,触发onUserChange函数
            })
        }
      }
    }
  • @Computed:用于声明计算属性,基于其他状态自动生成值。

    V1代码示例

    @Entry
    struct MyComponent {
      @State firstName: string = '张';
      @State lastName: string = '三';
    
      @Computed
      get fullName(): string {
        return `${this.firstName}${this.lastName}`; // 计算属性fullName基于firstName和lastName自动生成
      }
    
      build() {
        Column() {
          Text(`全名:${this.fullName}`)
        }
      }
    }

    二、V2版本的装饰器

           升级到V2版本后,这些装饰器也得到了相应的升级和优化,使用起来更加方便和强大。

  • @local:在V2版本中,@local装饰器的使用方式更加灵活。

    function addNumbers(@param a: number, @param b: number): number {
      return a + b;
    }
    
    // 如果传入非数字类型的参数,会在编译时报错
    let result = addNumbers(2, '3'); // 编译错误:参数b必须是number类型

    @once:在V2版本中,@once装饰器的实现方式更加高效。

    @Entry
    struct MyComponent {
      @State count: number = 0;
    
      @once
      init() {
        console.log('初始化函数只执行一次');
        this.count = 10;
      }
    
      build() {
        Column() {
          Button('增加计数')
            .onClick(() => {
              this.count++;
              this.init(); // 即使多次点击,init函数也只执行一次
            })
          Text(`计数:${this.count}`)
        }
      }
    }

    @Event:在V2版本中,@Event装饰器支持更多的事件类型。

    // 子组件
    @Entry
    struct ChildComponent {
      @Event onButtonClick: () => void;
      @Event onDataChange: (newData: string) => void;
    
      build() {
        Column() {
          Button('点击我')
            .onClick(() => {
              this.onButtonClick(); // 触发自定义事件
            })
          TextInput()
            .onChange((value) => {
              this.onDataChange(value); // 触发带参数的自定义事件
            })
        }
      }
    }
    
    // 父组件
    @Entry
    struct ParentComponent {
      build() {
        Column() {
          ChildComponent()
            .onButtonClick(() => {
              console.log('按钮被点击了');
            })
            .onDataChange((newData) => {
              console.log('数据发生变化:', newData);
            })
        }
      }
    }

    @monitor:在V2版本中,@monitor装饰器支持更细粒度的监听。

    @Entry
    struct MyComponent {
      @State user: { name: string; age: number } = { name: '张三', age: 20 };
    
      @monitor('name')
      onUserNameChange(newValue: string, oldValue: string) {
        console.log('用户名发生变化:', newValue, oldValue);
      }
    
      @monitor('age')
      onUserAgeChange(newValue: number, oldValue: number) {
        console.log('用户年龄发生变化:', newValue, oldValue);
      }
    
      build() {
        Column() {
          Button('修改用户信息')
            .onClick(() => {
              this.user = { name: '李四', age: 25 }; // 修改用户信息,触发对应的监听函数
            })
        }
      }
    }

    @Computed:在V2版本中,@Computed装饰器支持更复杂的计算逻辑。

    @Entry
    struct MyComponent {
      @State price: number = 100;
      @State quantity: number = 2;
    
      @Computed
      get total(): number {
        return this.price * this.quantity; // 计算属性total基于price和quantity自动生成
      }
    
      @Computed
      get discount(): number {
        return this.total > 200 ? this.total * 0.1 : 0; // 更复杂的计算逻辑
      }
    
      build() {
        Column() {
          Text(`总价:${this.total},折扣:${this.discount}`)
        }
      }
    }

           状态管理是构建动态交互应用的核心机制,而鸿蒙系统的装饰器模式为开发提供了高效、灵活的工具集。通过合理使用@State@Prop@Link等装饰器,开发者可以清晰定义数据流方向,实现组件间的高效通信,同时避免深拷贝和冗余渲染的性能陷阱。随着应用复杂度的提升,装饰器模式的优势愈发凸显:它使代码结构更清晰,维护成本更低,且能灵活应对需求变化。

    #HarmonyOS应用开发工具##Ark-TS语言#

### HarmonyOS V1V2状态管理的差异及适用场景比较 #### 一、核心概念对比 HarmonyOS状态管理模式在V1V2之间存在显著的变化。V1主要依赖于`@State`装饰器来定义可变变量,而这些变量通常由父组件控制并传递给子组件[^3]。相比之下,V2引入了更灵活的全局状态管理机制,允许通过`ts @ConsumeGlobal appTheme: string;`这样的语法直接消费全局状态[^1]。 这种设计上的变化使得开发者能够更加便捷地处理跨页面或复杂嵌套结构中的数据共享问题。然而,在实际项目中,尤其是针对那些已经基于V1构建的大规模应用程序而言,完全切换到V2可能会面临诸多挑战,因此混合使用的策略成为一种常见实践[^2]。 #### 二、技术特性分析 ##### 1. 数据绑定方式 - **V1**: 使用单向数据流模型,即父级设置好初始值并通过属性传入子组件;如果需要反馈更新,则需借助回调函数完成操作。 - **V2**: 支持更为直观的双向绑定模式,特别是当采用`@Link`修饰符时可以轻松达成父子间同步效果【注意这里提到的是关于链接而非具体版本间的转换】。 ##### 2. 性能表现考量 随着应用规模增大以及交互逻辑变得越来越复杂,V2凭借其优化后的内部实现能够在一定程度上减少不必要的重绘次数,从而提升整体渲染效率. 另外值得注意的一点是尽管两者都能满足大多数日常开发需求但在特定情况下比如频繁触发UI刷新或者涉及大量动态计算表达式的场合下,V2的优势会进一步显现出来因为它的架构更适合现代高效能移动体验的要求. ```typescript // 示例代码展示如何利用V2的新特性进行声明式编程风格编写业务逻辑部分. @Component struct MyComponent { @ConsumeGlobal themeColor:string; build(){ Column() { Text(`Current Theme Color is ${this.themeColor}`) .fontSize(20) } } } ``` 上述片段展示了怎样简单明了地接入系统级别的主题颜色配置项作为局部视图的一部分呈现给最终用户查看. #### §三、总结评价§ 综上所述,Harmoy OS所提供的两种不同层次的状态管理体系各有千秋适用于不同的软件工程阶段发展目标当中去考虑选用哪一类方案最为合适取决于团队当前技术水平积累程度还有对未来扩展性的预期规划等因素综合权衡之后再做决定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值