一、@Watch状态变量更改通知
@Watch应用于对状态变量的监听。如果开发者需要关注某个状态变量的值是否改变,可以使用@Watch为状态变量设置回调函数。
1、装饰器参数:必填。常量字符串,字符串需要有引号。是(string)=> void自定义成员函数的方法的引用。
2、可装饰的自定义组件变量:装饰器@State、 @Prop、@Link、@ObjectLink、@Provide、 @Consume、@StorageProp以及@StorageLink所装饰的变量均可以通过@Watch监听其变化。不允许监听常规变量。
3、装饰器的顺序:建议@State、@Prop、@Link等装饰器在@Watch装饰器之前。
示例代码:模拟购物车多选效果。显示多选的数量展示。选中的时候通过watch去监听到选中的状态。更新ui
import myList from '../components/myListWatch'
import Item from '../model/ItemFlag'@Entry
@Component
struct PageWatch {@State text: string = ''@Provide list: Item [] = [new Item(Date.now(), "房子"),new Item(Date.now(), "车子")]build() {Row() {Column() {Row(){Row() {CheckboxGroup({ group: "checkBoxGroup" })Text("全选")Button("删除").onClick(v => {this.list = this.list.filter(v =>!v.isChecked)}).margin({ left: "20" }).backgroundColor(Color.Red)}.margin({ top: "10", left: '20' })Summary()}.width("100%").justifyContent(FlexAlign.SpaceBetween)Row() {TextInput({ text: this.text }).width(250).onChange((value) => {this.text = value})Button("增加").onClick(() => {this.list.push(new Item(Date.now(), this.text))this.text = ""}).margin(10)}.width("100%").justifyContent(FlexAlign.SpaceBetween).margin(10)if (this.list.length) {ThisList()} else {Text("可你却总是笑我,一无所有")}}.width('100%').height('100%')}}
}@Component
struct ThisList {@Consume list: Item[];build() {Row() {List() {ForEach(this.list, (item, index) => {ListItem() {myList({ item, index })}.margin(10)})}.layoutWeight(1).divider({strokeWidth: 1,color: Color.Blue,startMargin: 10,endMargin: 10}).width('100%')}}
}@Component
struct Summary {@Consume list: Item[];build() {Row() {Text(`${this.getchecked()}/${this.getTotal()}`).fontSize(26).margin({'left':14})}}getchecked(){return this.list.filter(item=>item.isChecked).length}getTotal(){return this.list.length}
}
import Item from '../model/ItemFlag';
//自定义组件 组件与组件之间是隔离的
@Component
struct myListWatch {@Consume list: Item [];//把list注入进来 不用去传递了@ObjectLink @Watch("onItemChecked") item: Item;private index: number;onItemChecked(){console.log("checked")this.list.splice(this.index,1,this.item)//删除当前的对象,在插入一个改变了的对象}build() {Row() {Checkbox({group:"checkBoxGroup"}).select(this.item.isChecked).onChange(v=>{this.item.isChecked=vconsole.log(JSON.stringify(this.item))})Text(this.item.text).fontSize(20).decoration({type:this.item.isChecked?TextDecorationType.Underline:TextDecorationType.None,color:Color.Blue})Button("删除").backgroundColor(Color.Red).onClick(() => {this.list.splice(this.index, 1)})}.justifyContent(FlexAlign.SpaceBetween).width("100%")}
}export default myListObserved
@Observed class ItemFlag {id: number;text: string;isChecked:boolean;constructor(id: number, text: string,isChecked=false) {this.id = idthis.text = textthis.isChecked=isChecked}
}export default ItemFlag
二、页面间共享状态-LocalStorage
LocalStorage是页面级的UI状态存储,通过@Entry装饰器接收的参数可以在页面内共享同一个LoalStorage实例。LocalStorage也可以在UIAbility内,页面间共享状态。
LocalStorage根据与@Component装饰的组件的同步类型不同,提供了两个装饰器:
@LocalStorageProp: @LocalStorageProp装饰的变量和与LocalStorage中给定属性建立单向同步关系。
@LocalStorageLink: @LocalStorageLink装饰的变量和在@Component中创建与LocalStorage中给定属性建立双向同步关系。
import router from '@ohos.router'
let storage=LocalStorage.GetShared()
@Entry(storage)
@Component
struct PageLocalStorage {@State message: string = 'Hello World'// @LocalStorageProp("name") n: string = ''@LocalStorageLink("name") n: string = ''build() {Row() {Column() {Text(this.n).fontSize(50).fontWeight(FontWeight.Bold)Button("跳转").onClick(v => {router.pushUrl({url:"pages/PageLSDetail"})})Son1()}.width('100%')}.height('100%')}
}@Component
struct Son1{@LocalStorageLink("name") m:string =""build(){Row(){Text(`child-${this.m}`)}}
}
import router from '@ohos.router'let storage=LocalStorage.GetShared()
@Entry(storage)
@Component
struct PageLSDetail {@State message: string = 'Hello World'@LocalStorageLink("name") name:string=''build() {Row() {Column() {Text(this.name).fontSize(50).fontWeight(FontWeight.Bold)Button("返回").onClick(v => {this.name="車子"router.back()})}.width('100%')}.height('100%')}
}
import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from '@ohos.hilog';
import window from '@ohos.window';export default class EntryAbility extends UIAbility {storage:LocalStorage =new LocalStorage({name:"房子"})onCreate(want, launchParam) {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');}onDestroy() {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');}onWindowStageCreate(windowStage: window.WindowStage) {// Main window is created, set main page for this abilityhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');windowStage.loadContent('pages/PageLocalStorage', this.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) ?? '');});}onWindowStageDestroy() {// Main window is destroyed, release UI related resourceshilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');}onForeground() {// Ability has brought to foregroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');}onBackground() {// Ability has back to backgroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');}
}
三、AppStorage-应用全局的UI状态存储-非持久化
AppStorage是应用全局的UI状态存储,是和应用的进程绑定的,由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储。仅仅存储在内存当中。退出程序后。数据就丢失了。
AppStorage是在应用启动的时候会被创建的单例。它的目的是为了提供应用状态数据的中心存储,这些状态数据在应用级别都是可访问的。AppStorage将在应用运行过程保留其属性。属性通过唯一的键字符串值访问。
Appstorage可以和UI组件同步,且可以在应用业务逻辑中被访问。
AppStorage.SetOrCreate("name","房子")
@StorageProp("name") name:string =""
@StorageLink("name") appname: string = ''
四、PersistentStorage-持久化存储UI状态
PersistentStorage是应用程序中的可选单例对象。此对象的作用是持久化存储选定的AppStorage属性,以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同。
PersistentStorage允许的类型和值有:
1、number,stringboolean,enum 等简单类型
2、可以被SON.stringify0和SON.parse0重构的对象。例如Date, Map, Set等内置类型则不支持,以及对象的属性方法不支持持久化了
注意:
PersistentStorage的持久化变量最好是小于2kb的数据,不要大量的数据持久化,因为PersistentStorage写入磁盘的操作是同步的,大量的数据本地化读写会同步在UI线程中执行,影响UI渲染性能。如果开发者需要存储大量的数据,建议使用数据库api。
PersistentStorage只能在UI页面内使用,否则将无法持久化数据。
//只能在page页面中,才能持久化。
PersistentStorage.PersistProp("name","房子")
@StorageProp("name") name:string =""
@StorageLink("name") appname: string = ''