写点什么

HarmonyOS 5.0 应用开发——装饰器的使用

作者:高心星
  • 2024-11-28
    江苏
  • 本文字数:5490 字

    阅读完需:约 18 分钟

HarmonyOS 5.0应用开发——装饰器的使用

【高心星出品】

装饰器的使用

状态管理

组件状态管理

@state 组件内状态管理

@State 装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。当状态改变时,UI 会发生对应的渲染改变。



@Entry@Componentstruct MyComponent {    //状态变量  @State count: number = 0;
build() { Button(`点击次数: ${this.count}`) .onClick(() => { //更新状态变量 this.count += 1; }) }}
复制代码


状态变量在声明的时候必须要进行初始化。

对象类型的状态变量

创建 info 类


/** *作者:gxx *日期:2024-03-15 11:41:10 *介绍: *类型info **/export class info{  private name:string  private description:string
constructor(name:string,description:string) { this.name=name this.description=description } getname(){return this.name} getdes(){return this.description}}
复制代码


使用 info 对象


@Entry@Componentstruct Index {  @State message: string = 'Hello World'    //创建对象  @State pinfo:info=new info('gxx','a good teacher')  build() {    Row() {      Column() {        Row(){          Text(this.pinfo.getname())            .fontSize(20)            .fontWeight(FontWeight.Bolder)          Text(this.pinfo.getdes())            .fontSize(16)            .fontColor(Color.Gray)        }.width('100%')        .margin(3)        .padding(5)        .justifyContent(FlexAlign.SpaceAround)        .alignItems(VerticalAlign.Center)        Button('改变')          .width('60%')          .margin(10)          .onClick(()=>{            //改变对象 会动态刷新ui            this.pinfo=new info('ggl','a good man')          })      }      .width('100%')    }    .height('100%')  }}
复制代码
数组类型的状态变量
@Entry@Componentstruct Arraypage {  @State message: string = 'Hello World'  // 数组状态变量  @State arr: Array<string> = ['gxx', 'ggl', 'gxz', 'xyz']
build() { Row() { Column() { ForEach(this.arr, (item, index) => { Text((index + 1) + '. ' + item) .fontSize(22) .width('100%') .margin({ top: 5, bottom: 5 }) .padding(5) }, item => JSON.stringify(item)) Button('增加') .width('60%') .onClick(() => { // 数组添加元素 this.arr.push('abc') }) Button('减少') .width('60%') .onClick(() => { // 数组移除元素 this.arr.pop() }) .margin(10) } .width('100%') } .height('100%') }}
复制代码



@prop 父子组件单向同步

@Prop 装饰的变量可以和父组件建立单向的同步关系。@Prop 装饰的变量是可变的,但是变化不会同步回其父组件。


父组件变化,子组件跟着变。


子组件变化,父组件不受影响。


@Componentstruct child{  // 状态变量不能初始化,需要父组件传值  @Prop count:number  build(){    Column() {      Text('子组件内容:' + this.count)        .width('100%')        .fontSize(22)        .fontColor(Color.Red)      Button('子组件按钮')        .margin(5)        .width('60%')        .onClick(()=>{          this.count+=1        })    }    .width('100%')    .padding(5)    .margin({top:5,bottom:5})    .border({width:2,color:Color.Green,radius:5})  }}
@Entry@Componentstruct Propdemo { @State pcount:number=1
build() { Row() { Column() { // 子组件的状态变量由父组件初始化 child({count:this.pcount}) Text('父组件内容:' + this.pcount) .width('100%') .fontSize(22) Button('父组件按钮') .margin(5) .width('60%') .onClick(()=>{ this.pcount+=1 }) } .width('100%') } .height('100%') }}
复制代码



@link 父子组件双向同步

子组件中被 @Link 装饰的变量与其父组件中对应的数据源建立双向数据绑定。


@Componentstruct child{  // 状态变量不能初始化,需要父组件传值  @Link count:number  build(){    Column() {      Text('子组件内容:' + this.count)        .width('100%')        .fontSize(22)        .fontColor(Color.Red)      Button('子组件按钮')        .margin(5)        .width('60%')        .onClick(()=>{          this.count+=1        })    }    .width('100%')    .padding(5)    .margin({top:5,bottom:5})    .border({width:2,color:Color.Green,radius:5})  }}
@Entry@Componentstruct Propdemo { @State pcount:number=1 build() { Row() { Column() { // 子组件的状态变量由父组件初始化 child({count:$pcount}) Text('父组件内容:' + this.pcount) .width('100%') .fontSize(22) Button('父组件按钮') .margin(5) .width('60%') .onClick(()=>{ this.pcount+=1 }) } .width('100%') } .height('100%') }}
复制代码



@watch 状态变量观察者

@Watch 应用于对状态变量的监听。如果开发者需要关注某个状态变量的值是否改变,可以使用 @Watch 为状态变量设置回调函数,常与 @state、@prop、@link 配合使用。



@Entry@Componentstruct Watchdemo { @State message: string = 'Hello World' // 观察者声明 @State @Watch('watchfun') num:number=1 @State col:Color=Color.Red // 观察者对应的监听函数 name就是观察变量的名字 watchfun(name:string) { console.info('gxx num改变了') if(this.num>10){ this.col=Color.Orange } } build() { Row() { Column() { Text(`当前次数:${this.num}`) .fontSize(30) .fontWeight(FontWeight.Bold) .padding(10) .border({width:1,color:Color.Green,radius:5}) .backgroundColor(this.col) .onClick(()=>{ this.num+=1 }) } .width('100%') } .height('100%') }}
复制代码



应用状态管理

LocalStorage 页面级共享数据

LocalStorage 是页面级的 UI 状态存储,通过 @Entry 装饰器接收的参数可以在页面内共享同一个 LocalStorage 实例。LocalStorage 也可以在 UIAbility 实例内,在页面间共享状态。

页面内部共享数据

LocalStorage 可以实现页面内部各个组件的数据共享。


// 声明一个localstoragelet stt=new LocalStorage({aa:44})@Componentstruct child{   // 单向同步绑定了num num改变不会影响stt   @LocalStorageProp('aa') num:number=1  build(){    Text('child: '+this.num)      .width('100%')      .padding(5)      .fontSize(25)      .onClick(()=>{        this.num+=1      })      .border({width:2,color:Color.Blue,radius:5})  }}@Entry (stt)@Componentstruct Index {  @State message: string = 'Hello World'  // 双向绑定count count改变stt一样会改变  @LocalStorageLink('aa') count: number = 1  build() {    Row() {      Column() {        child()        Text('index: ' + this.count)          .width('100%')          .fontSize(25)          .padding(5)          .onClick(()=>{            this.count+=1          })          .margin({top:20})          .border({width:2,color:Color.Red,radius:5})      }      .width('100%')    }    .height('100%')  }}
复制代码
页面间共享数据

LocalStorage 还可以应用在多个页面之间,用于页面间数据共享。


EntryAbility 文件中加载 localstorage


onWindowStageCreate(windowStage: window.WindowStage) {    // Main window is created, set main page for this ability    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');    // 声明一个storage    let storage=new LocalStorage({'jj':10})    // 加载页面的时候指定storage    windowStage.loadContent('pages/apage',storage, (err, data) => {      if (err.code) {        hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');        return;      }      hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');    });  }
复制代码


apage 中获取共享数据


import router from '@ohos.router'// 取出该storagelet storage=LocalStorage.GetShared()@Entry(storage)@Componentstruct Apage {  @State message: string = 'Hello World'  // 初始化给anum  @LocalStorageLink('jj') anum:number=1  build() {    Row() {      Column() {        Text('全局数据:'+this.anum)          .fontSize(25)          .fontWeight(FontWeight.Bold)          .border({width:2,color:Color.Red,radius:5})          .onClick(()=>{            this.anum+=1          })          Button('跳转')          .onClick(()=>{            router.pushUrl({              url: "pages/bpage"            })          })            .width('60%')            .margin({top:10})      }      .width('100%')    }    .height('100%')  }}
复制代码


bpage 中获取共享数据


// 取出该storagelet storage=LocalStorage.GetShared()@Entry(storage)@Componentstruct Bpage {  @State message: string = 'Hello World'  // 初始化给bnum  @LocalStorageLink('jj') bnum:number=1  build() {    Row() {      Column() {        Text('全局数据:'+this.bnum)          .fontSize(25)          .fontWeight(FontWeight.Bold)          .border({width:2,color:Color.Red,radius:5})          .onClick(()=>{            this.bnum+=1          })      }      .width('100%')    }    .height('100%')  }}
复制代码

AppStorage 应用全局数据

AppStorage 是在应用启动的时候会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。AppStorage 将在应用运行过程保留其属性。属性通过唯一的键字符串值访问。


相对于 localstorage,appstroage 应用更灵活范围更大,可以在自定义组件,自定义对话框中使用。


 // 设置一个全局存储器    AppStorage.SetOrCreate('pp',20) // 直接拿来使用  @StorageLink('pp') apnum:number=1
复制代码

PersistentStorage 持久化全局数据

PersistentStorage 将选定的 AppStorage 属性保留在设备磁盘上。应用程序通过 API,以决定哪些 AppStorage 属性应借助 PersistentStorage 持久化。UI 和业务逻辑不直接访问 PersistentStorage 中的属性,所有属性访问都是对 AppStorage 的访问,AppStorage 中的更改会自动同步到 PersistentStorage。



注意:目前无法在虚拟机中演示效果


//初始化持久数据PersistentStorage.PersistProp('aProp', 47);
@Entry@Componentstruct Index { @State message: string = 'Hello World' @StorageLink('aProp') aProp: number = 48
build() { Row() { Column() { Text(this.message) // 应用退出时会保存当前结果。重新启动后,会显示上一次的保存结果 Text(`${this.aProp}`) .onClick(() => { this.aProp += 1; }) } } }}
复制代码


具体执行流程如下:



  • 触发点击事件后:

  • 状态变量 @StorageLink('aProp') aProp 改变,触发 Text 组件重新刷新。

  • @StorageLink 装饰的变量是和 AppStorage 中建立双向同步的,所以 @StorageLink('aProp') aProp 的变化会被同步回 AppStorage 中。

  • AppStorage 中“aProp”属性的改变会同步到所有绑定该“aProp”的单向或者双向变量,在本示例中没有其他的绑定“aProp”的变量。

  • 因为“aProp”对应的属性已经被持久化,所以在 AppStorage 中“aProp”的改变会触发 PersistentStorage 将新的改变写入本地磁盘。

  • 后续启动应用:

  • 执行 PersistentStorage.PersistProp('aProp', 47),在首先查询在 PersistentStorage 本地文件查询“aProp”属性,成功查询到。

  • 将在 PersistentStorage 查询到的值写入 AppStorage 中。

  • 在 Index 组件里,@StorageLink 绑定的“aProp”为 PersistentStorage 写入 AppStorage 中的值,即为上一次退出应用存入的值。

Environment 设备环境信息

Environment 是 ArkUI 框架在应用程序启动时创建的单例对象。它为 AppStorage 提供了一系列描述应用程序运行状态的属性。


Environment 设备参数



注意:对于 environment 只能查询信息,不能修改信息。


// 将languagecode写入appstorageEnvironment.EnvProp('languageCode','cn')  // 直接获取该值  @StorageProp('languageCode') mode:string='cn'
复制代码


用户头像

高心星

关注

天将降大任于斯人也,必先苦其心志。 2024-10-17 加入

华为开发者专家(HDE)。 10年教学经验,兼任多家科技公司技术顾问。先后从事JavaEE项目开发、Python爬虫、HarmonyOS移动应用开发等课程的教学工作。参与开发《鸿蒙应用开发基础》和《鸿蒙项目实战》等课程。

评论

发布
暂无评论
HarmonyOS 5.0应用开发——装饰器的使用_huawei_高心星_InfoQ写作社区