网站优化培训,如何利用云服务器进行网站建设,wordpress卸载,做网站的公司没有技术在声明式UI编程框架中#xff0c;UI是程序状态的运行结果#xff0c;用户构建了一个UI模型#xff0c;其中应用的运行时的状态是参数。当参数改变时#xff0c;UI作为返回结果#xff0c;也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染#xff0c;在ArkU…在声明式UI编程框架中UI是程序状态的运行结果用户构建了一个UI模型其中应用的运行时的状态是参数。当参数改变时UI作为返回结果也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染在ArkUI中统称为状态管理机制。
一、装饰器总览
ArkUI提供了多种装饰器根据状态变量的影响范围将所有的装饰器可以大致分为
管理组件拥有状态的装饰器组件级别的状态管理可以观察组件内变化和不同组件层级的变化但需要同一个页面内。管理应用拥有状态的装饰器应用级别的状态管理可以观察不同页面甚至不同UIAbility的状态变化是应用内全局的状态管理。
上图中Components部分的装饰器为组件级别的状态管理Application部分为应用的状态管理。
管理组件拥有的状态即图中Components级别的状态管理
StateState装饰的变量拥有其所属组件的状态可以作为其子组件单向和双向同步的数据源。当其数值改变时会引起相关组件的渲染刷新。PropProp装饰的变量可以和父组件建立单向同步关系Prop装饰的变量是可变的但修改不会同步回父组件。LinkLink装饰的变量和父组件构建双向同步关系的状态变量父组件会接受来自Link装饰的变量的修改的同步父组件的更新也会同步给Link装饰的变量。Provide/ConsumeProvide/Consume装饰的变量用于跨组件层级多层组件同步状态变量可以不需要通过参数命名机制传递通过alias别名或者属性名绑定。ObservedObserved装饰class需要观察多层嵌套场景的class需要被Observed装饰。单独使用Observed没有任何作用需要和ObjectLink、Prop连用。ObjectLinkObjectLink装饰的变量接收Observed装饰的class的实例应用于观察多层嵌套场景和父组件的数据源构建双向同步。
管理应用拥有的状态即图中Application级别的状态管理
LocalStorage页面级UI状态存储通常用于UIAbility内、页面间的状态共享。AppStorage特殊的单例LocalStorage对象由UI框架在应用程序启动时创建为应用程序UI状态属性提供中央存储。PersistentStorage持久化存储UI状态通常和AppStorage配合使用选择AppStorage存储的数据写入磁盘以确保这些属性在应用程序重新启动时的值与应用程序关闭时的值相同。Environment应用程序运行的设备的环境参数环境参数会同步到AppStorage中可以和AppStorage搭配使用。
其他状态管理功能
Watch用于监听状态变量的变化。$$运算符给内置组件提供TS变量的引用使得TS变量和内置组件的内部状态保持同步。
二、管理组件拥有的状态
1、State装饰器组件内状态
State装饰的变量或称为状态变量一旦变量拥有了状态属性就和自定义组件的渲染绑定起来。当状态改变时UI会发生对应的渲染改变。
State装饰的变量拥有以下特点
State装饰的变量与子组件中的Prop装饰变量之间建立单向数据同步,与Link、ObjectLink装饰变量之间建立双向数据同步。State装饰的变量生命周期与其所属自定义组件的生命周期相同。支持多种数据类型允许 Object、class、string、number、boolean、enum、Date类型以及这些类型的数组。内部私有标记为 State 的属性是私有变量只能在组件内访问。支持多个实例组件不同实例的内部状态数据独立。需要本地初始化必须为所有 State 变量分配初始值将变量保持未初始化可能导致框架行为未定义初始值需要是有意义的值比如设置 class 类型的值为 null 就是无意义的会导致编译报错。创建自定义组件时支持通过状态变量名设置初始值在创建组件实例时可以通过变量名显式指定 State 状态属性的初始值。
装饰class对象类型的变量 当装饰的数据类型为class或者Object时可以观察到自身的赋值的变化和其属性赋值的变化即Object.keys(observedObject)返回的所有属性
创建一个Model对象
class Model {public value: string;constructor(value: string) {this.value value;}
}在父组件中初始化State装饰对象父组件初始化将会覆盖本地初始化。
Entry
Component
struct EntryComponent {build() {Column() {// 此处指定的参数都将在初始渲染时覆盖本地定义的默认值并不是所有的参数都需要从父组件初始化MyComponent({ count: 1, increaseBy: 2 }).width(300)MyComponent({ title: new Model(Hello World 2), count: 7 })}}
}在本地初始化State装饰对象State变量更新会触发组件UI更新
Component
struct MyComponent {State title: Model new Model(Hello World);State count: number 0;private increaseBy: number 1;build() {Column() {Text(${this.title.value}).margin(10)Button(Click to change title).onClick(() {// State变量的更新将触发上面的Text组件内容更新this.title.value this.title.value Hello ArkUI ? Hello World : Hello ArkUI;}).width(300).margin(10)Button(Click to increase count ${this.count}).onClick(() {// State变量的更新将触发该Button组件的内容更新this.count this.increaseBy;}).width(300).margin(10)}}
}2、Prop装饰器父子单向同步
Prop装饰的变量可以和父组件建立单向的同步关系。Prop装饰的变量是可变的但是变化不会同步回其父组件。
Prop装饰的变量拥有以下特点
支持简单数据类型仅支持 number 、 string 、 boolean、Object、class、enum 类型内部私有标记为 Prop 的属性是私有变量只能在组件内访问。支持多个实例组件不同实例的内部状态数据独立。Prop装饰器不能在Entry装饰的自定义组件中使用。
Component
struct CountDownComponent {Prop count: number 0;costOfOneAttempt: number 1;build() {Column() {if (this.count 0) {Text(You have ${this.count} Nuggets left)} else {Text(Game over!)}// Prop装饰的变量不会同步给父组件Button(Try again).onClick(() {this.count - this.costOfOneAttempt;})}}
}Entry
Component
struct ParentComponent {State countDownStartValue: number 10;build() {Column() {Text(Grant ${this.countDownStartValue} nuggets to play.)// 父组件的数据源的修改会同步给子组件Button(1 - Nuggets in New Game).onClick(() {this.countDownStartValue 1;})// 父组件的修改会同步给子组件Button(-1 - Nuggets in New Game).onClick(() {this.countDownStartValue - 1;})CountDownComponent({ count: this.countDownStartValue, costOfOneAttempt: 2 })}}
}3、Link装饰器父子双向同步
子组件中被Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。Link装饰的变量与其父组件中的数据源共享相同的值。
Link装饰的变量拥有以下特点
Object、class、string、number、boolean、enum类型以及这些类型的数组。支持Date类型。内部私有标记为 Link 的属性是私有变量只能在组件内访问。支持多个实例组件不同实例的内部状态数据独立。不支持内部初始化在创建组件的新实例时必须将值传递给 Link 修饰的变量进行初始化不支持在组件内部进行初始化。
class GreenButtonState {width: number 0;constructor(width: number) {this.width width;}
}Component
struct GreenButton {Link greenButtonState: GreenButtonState;build() {Button(Green Button).width(this.greenButtonState.width).height(40).backgroundColor(#64bb5c).fontColor(#FFFFFF90%).onClick(() {if (this.greenButtonState.width 700) {// 更新class的属性变化可以被观察到同步回父组件this.greenButtonState.width 60;} else {// 更新class变化可以被观察到同步回父组件this.greenButtonState new GreenButtonState(180);}})}
}Component
struct YellowButton {Link yellowButtonState: number;build() {Button(Yellow Button).width(this.yellowButtonState).height(40).backgroundColor(#f7ce00).fontColor(#FFFFFF90%).onClick(() {// 子组件的简单类型可以同步回父组件this.yellowButtonState 40.0;})}
}Entry
Component
struct ShufflingContainer {State greenButtonState: GreenButtonState new GreenButtonState(180);State yellowButtonProp: number 180;build() {Column() {Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center }) {// 简单类型从父组件State向子组件Link数据同步Button(Parent View: Set yellowButton).width(312).height(40).margin(12).fontColor(#FFFFFF90%).onClick(() {this.yellowButtonProp (this.yellowButtonProp 700) ? this.yellowButtonProp 40 : 100;})// class类型从父组件State向子组件Link数据同步Button(Parent View: Set GreenButton).width(312).height(40).margin(12).fontColor(#FFFFFF90%).onClick(() {this.greenButtonState.width (this.greenButtonState.width 700) ? this.greenButtonState.width 100 : 100;})// class类型初始化LinkGreenButton({ greenButtonState: $greenButtonState }).margin(12)// 简单类型初始化LinkYellowButton({ yellowButtonState: $yellowButtonProp }).margin(12)}}}
}1.点击子组件GreenButton和YellowButton中的Button子组件会发生相应变化将变化同步给父组件。因为Link是双向同步会将变化同步给State。
2.当点击父组件ShufflingContainer中的Button时State变化也会同步给Link子组件也会发生对应的刷新。
三、管理应用拥有的状态
1、LocalStorage页面级UI状态存储
LocalStorage是页面级的UI状态存储通过Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage支持UIAbility实例内多个页面间状态共享。 LocalStorage是ArkTS为构建页面级别状态变量提供存储的内存内“数据库”。
应用程序可以创建多个LocalStorage实例LocalStorage实例可以在页面内共享也可以通过GetShared接口实现跨页面、UIAbility实例内共享。组件树的根节点即被Entry装饰的Component可以被分配一个LocalStorage实例此组件的所有子组件实例将自动获得对该LocalStorage实例的访问权限。被Component装饰的组件最多可以访问一个LocalStorage实例和AppStorage未被Entry装饰的组件不可被独立分配LocalStorage实例只能接受父组件通过Entry传递来的LocalStorage实例。一个LocalStorage实例在组件树上可以被分配给多个组件。LocalStorage中的所有属性都是可变的。
LocalStorage根据与Component装饰的组件的同步类型不同提供了两个装饰器
LocalStoragePropLocalStorageProp装饰的变量和与LocalStorage中给定属性建立单向同步关系。LocalStorageLinkLocalStorageLink装饰的变量和在Component中创建与LocalStorage中给定属性建立双向同步关系。
2、AppStorage应用全局的UI状态存储
AppStorage是应用全局的UI状态存储是和应用的进程绑定的由UI框架在应用程序启动时创建为应用程序UI状态属性提供中央存储。
和AppStorage不同的是LocalStorage是页面级的通常应用于页面内的数据共享。而AppStorage是应用级的全局状态共享还相当于整个应用的“中枢”持久化数据PersistentStorage和环境变量Environment都是通过AppStorage中转才可以和UI交互。
StorageProp
单向同步从AppStorage的对应属性到组件的状态变量。Object、 class、string、number、boolean、enum类型以及这些类型的数组。组件本地的修改是允许的但是AppStorage中给定的属性一旦发生变化将覆盖本地的修改。StorageProp不支持从父节点初始化只能AppStorage中key对应的属性初始化如果没有对应key的话将使用本地默认值初始化。
StorageLink
StorageLink(key) 装饰的变量是组件内部的状态数据当这些状态数据被修改时将会调用所在组件的 build() 方法进行UI刷新。组件通过使用 StorageLink(key) 装饰的状态变量与 AppStorage 建立双向数据绑定。
支持多种数据类型支持的数据类型和 State 一致且支持 object 。需要本地初始化必须为所有 StorageLink 变量分配初始值。数据状态全局化使用 StorageLink 修饰的数据变化后全局都会改变。数据持久化通过搭配 PersistentStorage 接口实现数据持久化。
Entry Component struct ComponentTest {StorageLink(time) time: string 1648643734154;// 使用StorageLink标记并初始化build() {Column({space: 10}) {Text(父组件【${this.time}】) // 使用time值.fontSize(20).backgroundColor(Color.Pink)Button(更新时间).onClick(() {this.time new Date().getTime().toString();// 更改time的值})}.width(100%).height(100%).padding(10)}
}四、其他状态管理
1、Watch装饰器状态变量更改通知
Watch 用来监听状态变量的变化当它修饰的状态变量发生变更时回调相应的方式
当观察到状态变量的变化的时候对应的Watch的回调方法将被触发Watch方法在自定义组件的属性变更之后同步执行如果在Watch的方法里改变了其他的状态变量也会引起状态变更和Watch的执行在第一次初始化的时候Watch装饰的方法不会被调用即认为初始化不是状态变量的改变。只有在后续状态改变时才会调用Watch回调方法。为了避免循环的产生建议不要在Watch的回调方法里修改当前装饰的状态变量不建议在Watch函数中调用async await异步行为可能会导致重新渲染速度的性能问题。
//给状态变量 count 增加一个 Watch 装饰器通过 Watch 注册一个回调方法 function_name
State Watch(function_name) count : number 0;//当状态变量 count 被改变时 触发 function_name 回调。
function_name(propName: string): void {}2、Watch和自定义组件更新
Component
struct TotalView {Prop Watch(onCountUpdated) count: number 0;State total: number 0;// Watch 回调onCountUpdated(propName: string): void {this.total this.count;}build() {Text(Total: ${this.total})}
}Entry
Component
struct CountModifier {State count: number 0;build() {Column() {Button(add to basket).onClick(() {this.count})TotalView({ count: this.count })}}
}3、$$语法内置组件双向同步
$$运算符为系统内置组件提供TS变量的引用使得TS变量和系统内置组件的内部状态保持同步。 以TextInput方法的text参数为例
Entry
Component
struct TextInputExample {State text: string controller: TextInputController new TextInputController()build() {Column({ space: 20 }) {Text(this.text)TextInput({ text: $$this.text, placeholder: input your word..., controller: this.controller }).placeholderColor(Color.Grey).placeholderFont({ size: 14, weight: 400 }).caretColor(Color.Blue).width(300)}.width(100%).height(100%).justifyContent(FlexAlign.Center)}
}