建站公司人员配置,如何利用网站推广业务,国外企业网络平台,wordpress 7天热门AppStorage#xff1a;应用全局的UI状态存储
AppStorage是应用全局的UI状态存储#xff0c;是和应用的进程绑定的#xff0c;由UI框架在应用程序启动时创建#xff0c;为应用程序UI状态属性提供中央存储。
和LocalStorage不同的是#xff0c;LocalStorage是页面级的应用全局的UI状态存储
AppStorage是应用全局的UI状态存储是和应用的进程绑定的由UI框架在应用程序启动时创建为应用程序UI状态属性提供中央存储。
和LocalStorage不同的是LocalStorage是页面级的通常应用于页面内的数据共享。而对于AppStorage是应用级的全局状态共享。
概述 AppStorage是在应用启动的时候会被创建的单例。它的目的是为了提供应用状态数据的中心存储这些状态数据在应用级别都是可访问的。AppStorage将在应用运行过程保留其属性。属性通过唯一的键字符串值访问。
AppStorage可以和UI组件同步且可以在应用业务逻辑中被访问。
AppStorage中的属性可以被双向同步数据可以是存在于本地或远程设备上并具有不同的功能比如数据持久化。
StorageProp 在上文中已经提到如果要建立AppStorage和自定义组件的联系需要使用StorageProp和StorageLink装饰器。使用StorageProp(key)/StorageLink(key)装饰组件内的变量key标识了AppStorage的属性。
当自定义组件初始化的时候StorageProp(key)/StorageLink(key)装饰的变量会通过给定的key绑定在AppStorage对应的属性完成初始化。本地初始化是必要的因为无法保证AppStorage一定存在给定的key这取决于应用逻辑是否在组件初始化之前在AppStorage实例中存入对应的属性。
StorageProp(key)是和AppStorage中key对应的属性建立单向数据同步我们允许本地改变的发生但是对于StorageProp本地的修改永远不会同步回AppStorage中相反如果AppStorage给定key的属性发生改变改变会被同步给StorageProp并覆盖掉本地的修改。
装饰器使用规则说明 StorageProp变量装饰器 说明 装饰器参数 key常量字符串必填字符串需要有引号。 允许装饰的变量类型 Object class、string、number、boolean、enum类型以及这些类型的数组。 类型必须被指定且必须和LocalStorage中对应属性相同。不支持any不允许使用undefined和null。 同步类型 单向同步从AppStorage的对应属性到组件的状态变量。 组件本地的修改是允许的但是AppStorage中给定的属性一旦发生变化将覆盖本地的修改。 被装饰变量的初始值 必须指定如果AppStorage实例中不存在属性则作为初始化默认值并存入AppStorage中。
变量的传递/访问规则说明 传递/访问 说明 从父节点初始化和更新 禁止StorageProp不支持从父节点初始化只能AppStorage中key对应的属性初始化如果没有对应key的话将使用本地默认值初始化 初始化子节点 支持可用于初始化State、Link、Prop、Provide。 是否支持组件外访问 否。
图1 StorageProp初始化规则图示 观察变化和行为表现 观察变化
当装饰的数据类型为boolean、string、number类型时可以观察到数值的变化。当装饰的数据类型为class或者Object时可以观察到赋值和属性赋值的变化即Object.keys(observedObject)返回的所有属性。当装饰的对象是array时可以观察到数组添加、删除、更新数组单元的变化。
框架行为
当StorageProp(key)装饰的数值改变被观察到时修改不会被同步回AppStorage对应属性键值key的属性中。当前StorageProp(key)单向绑定的数据会被修改即仅限于当前组件的私有成员变量改变其他的绑定该key的数据不会同步改变。当StorageProp(key)装饰的数据本身是状态变量它的改变虽然不会同步回AppStorage中但是会引起所属的自定义组件的重新渲染。当AppStorage中key对应的属性发生改变时会同步给所有StorageProp(key)装饰的数据StorageProp(key)本地的修改将被覆盖。
StorageLink StorageLink(key)是和AppStorage中key对应的属性建立双向数据同步
本地修改发生该修改会被写回AppStorage中AppStorage中的修改发生后该修改会被同步到所有绑定AppStorage对应key的属性上包括单向StorageProp和通过Prop创建的单向绑定变量、双向StorageLink和通过Link创建的双向绑定变量变量和其他实例比如PersistentStorage。
装饰器使用规则说明 StorageLink变量装饰器 说明 装饰器参数 key常量字符串必填字符串需要有引号。 允许装饰的变量类型 Object、class、string、number、boolean、enum类型以及这些类型的数组。 类型必须被指定且必须和AppStorage中对应属性相同。不支持any不允许使用undefined和null。 同步类型 双向同步从AppStorage的对应属性到自定义组件从自定义组件到AppStorage对应属性。 被装饰变量的初始值 必须指定如果AppStorage实例中不存在属性则作为初始化默认值并存入AppStorage中。
变量的传递/访问规则说明 传递/访问 说明 从父节点初始化和更新 禁止。 初始化子节点 支持可用于初始化常规变量、State、Link、Prop、Provide。 是否支持组件外访问 否。
图2 StorageLink初始化规则图示 观察变化和行为表现 观察变化
当装饰的数据类型为boolean、string、number类型时可以观察到数值的变化。当装饰的数据类型为class或者Object时可以观察到赋值和属性赋值的变化即Object.keys(observedObject)返回的所有属性。当装饰的对象是array时可以观察到数组添加、删除、更新数组单元的变化。
框架行为
当StorageLink(key)装饰的数值改变被观察到时修改将被同步回AppStorage对应属性键值key的属性中。AppStorage中属性键值key对应的数据一旦改变属性键值key绑定的所有的数据包括双向StorageLink和单向StorageProp都将同步修改当StorageLink(key)装饰的数据本身是状态变量它的改变不仅仅会同步回AppStorage中还会引起所属的自定义组件的重新渲染。
使用场景 从应用逻辑使用AppStorage和LocalStorage AppStorage是单例它的所有API都是静态的使用方法类似于LocalStorage对应的非静态方法。
AppStorage.SetOrCreate(PropA, 47);let storage: LocalStorage new LocalStorage({ PropA: 17 });
let propA: number AppStorage.Get(PropA) // propA in AppStorage 47, propA in LocalStorage 17
var link1: SubscribedAbstractPropertynumber AppStorage.Link(PropA); // link1.get() 47
var link2: SubscribedAbstractPropertynumber AppStorage.Link(PropA); // link2.get() 47
var prop: SubscribedAbstractPropertynumber AppStorage.Prop(PropA); // prop.get() 47link1.set(48); // two-way sync: link1.get() link2.get() prop.get() 48
prop.set(1); // one-way sync: prop.get()1; but link1.get() link2.get() 48
link1.set(49); // two-way sync: link1.get() link2.get() prop.get() 49storage.get(PropA) // 17
storage.set(PropA, 101);
storage.get(PropA) // 101AppStorage.Get(PropA) // 49
link1.get() // 49
link2.get() // 49
prop.get() // 49
从UI内部使用AppStorage和LocalStorage StorageLink变量装饰器与AppStorage配合使用正如LocalStorageLink与LocalStorage配合使用一样。此装饰器使用AppStorage中的属性创建双向数据同步。
AppStorage.SetOrCreate(PropA, 47);
let storage new LocalStorage({ PropA: 48 });Entry(storage)
Component
struct CompA {StorageLink(PropA) storLink: number 1;LocalStorageLink(PropA) localStorLink: number 1;build() {Column({ space: 20 }) {Text(From AppStorage ${this.storLink}).onClick(() this.storLink 1)Text(From LocalStorage ${this.localStorLink}).onClick(() this.localStorLink 1)}}
}
以持久化方式订阅某个事件并接收事件回调 推荐使用持久化方式订阅某个事件并接收事件回调可以减少开销增强代码的可读性。
// xxx.ets
import emitter from ohos.events.emitter;let NextID: number 0;class ViewData {title: string;uri: Resource;color: Color Color.Black;id: number;constructor(title: string, uri: Resource) {this.title title;this.uri urithis.id NextID;}
}Entry
Component
struct Gallery2 {dataList: ArrayViewData [new ViewData(flower, $r(app.media.icon)), new ViewData(OMG, $r(app.media.icon)), new ViewData(OMG, $r(app.media.icon))]scroller: Scroller new Scroller()private preIndex: number -1build() {Column() {Grid(this.scroller) {ForEach(this.dataList, (item: ViewData) {GridItem() {TapImage({uri: item.uri,index: item.id})}.aspectRatio(1).onClick(() {if (this.preIndex item.id) {return}var innerEvent { eventId: item.id }// 选中态黑变红var eventData {data: {colorTag: 1}}emitter.emit(innerEvent, eventData)if (this.preIndex ! -1) {console.info(preIndex: ${this.preIndex}, index: ${item.id}, black)var innerEvent { eventId: this.preIndex }// 取消选中态红变黑var eventData {data: {colorTag: 0}}emitter.emit(innerEvent, eventData)}this.preIndex item.id})}, (item: ViewData) JSON.stringify(item))}.columnsTemplate(1fr 1fr)}}
}Component
export struct TapImage {State tapColor: Color Color.Black;private index: number;private uri: Resource;onTapIndexChange(colorTag: emitter.EventData) {this.tapColor colorTag.data.colorTag ? Color.Red : Color.Black}aboutToAppear() {//定义事件IDvar innerEvent { eventId: this.index }emitter.on(innerEvent, this.onTapIndexChange.bind(this))}build() {Column() {Image(this.uri).objectFit(ImageFit.Cover).border({ width: 5, style: BorderStyle.Dotted, color: this.tapColor })}}
}
以下示例为消息机制方式订阅事件会导致回调监听的节点数较多非常耗时不推荐以此来实现应用代码。
// xxx.ets
class ViewData {title: string;uri: Resource;color: Color Color.Black;constructor(title: string, uri: Resource) {this.title title;this.uri uri}
}Entry
Component
struct Gallery2 {dataList: ArrayViewData [new ViewData(flower, $r(app.media.icon)), new ViewData(OMG, $r(app.media.icon)), new ViewData(OMG, $r(app.media.icon))]scroller: Scroller new Scroller()build() {Column() {Grid(this.scroller) {ForEach(this.dataList, (item: ViewData, index?: number) {GridItem() {TapImage({uri: item.uri,index: index})}.aspectRatio(1)}, (item: ViewData, index?: number) {return JSON.stringify(item) index;})}.columnsTemplate(1fr 1fr)}}
}Component
export struct TapImage {StorageLink(tapIndex) Watch(onTapIndexChange) tapIndex: number -1;State tapColor: Color Color.Black;private index: number;private uri: Resource;// 判断是否被选中onTapIndexChange() {if (this.tapIndex 0 this.index this.tapIndex) {console.info(tapindex: ${this.tapIndex}, index: ${this.index}, red)this.tapColor Color.Red;} else {console.info(tapindex: ${this.tapIndex}, index: ${this.index}, black)this.tapColor Color.Black;}}build() {Column() {Image(this.uri).objectFit(ImageFit.Cover).onClick(() {this.tapIndex this.index;}).border({ width: 5, style: BorderStyle.Dotted, color: this.tapColor })}}
}
限制条件 AppStorage与PersistentStorage以及Environment配合使用时需要注意以下几点
在AppStorage中创建属性后调用PersistentStorage.PersistProp()接口时会使用在AppStorage中已经存在的值并覆盖PersistentStorage中的同名属性所以建议要使用相反的调用顺序如果在AppStorage中已经创建属性后再调用Environment.EnvProp()创建同名的属性会调用失败。因为AppStorage已经有同名属性Environment环境变量不会再写入AppStorage中所以建议AppStorage中属性不要使用Environment预置环境变量名。