提示:本文根据b站尚硅谷2024最新鸿蒙开发HarmonyOS4.0+鸿蒙NEXT星河版零基础教程课整理
链接指引 => 尚硅谷2024最新鸿蒙开发HarmonyOS4.0+鸿蒙NEXT星河版零基础教程
一、状态管理入门
为了方便开发者管理组件状态,ArkTS
提供了一系列状态相关的装饰器,例如@State
,@Prop
,@Link
,@Provide
和@Consume
等等。
1.1 @State
@State
用于装饰当前组件的状态变量,@State
装饰的变量发生变化时会驱动当前组件的视图刷新。
注意:@State装饰的变量必须进行本地初始化。
具体语法如下
@State count:number = 1;
1.2 @Prop
@Prop
也可用于装饰状态变量,@Prop
装饰的变量发生变化时也会驱动当前组件的视图刷新,除此之外,@Prop
装饰的变量还可以同步父组件中的状态变量,但只能单向同步,也就是父组件的状态变化会自动同步到子组件,而子组件的变化不会同步到父组件。
注意:@Prop装饰的变量不允许本地初始化,只能通过父组件向子组件传参进行初始化。
具体语法如下:
父组件
@Entry
@Component
struct Parent{
@State count:number = 1;
build(){
Column(){
Child({count:this.count});
}
}
}
子组件
@Component
export struct Child{
@Prop count:number;
build(){
Text(this.count.toString());
}
}
1.3 @Link
@Link
也可用于装饰状态变量,@Link
装饰的变量发生变化时也会驱动当前组件的视图刷新,除此之外,@Link
变量同样会同步父组件状态,并且能够双向同步。也就是父组件的变化会同步到子组件,子组件的变化也会同步到父组件。
注意:@Link
装饰的变量不允许本地初始化,只能由父组件通过传参进行初始化,并且父组件必须使用$变量名
的方式传参,以表示传递的是变量的引用。
具体语法如下
父组件
@Entry
@Component
struct Parent{
@State count:number = 1;
build(){
Column(){
Child({count:$count});
}
}
}
子组件
@Component
export struct Child{
@Link count:number;
build(){
Text(this.count.toString());
}
}
1.4 @Provide和@Consume
@Provide
和@Consume
用于跨组件层级传递状态信息,其中@Provide
用于装饰祖先组件的状态变量,@Consume
用于装饰后代组件的状态变量。可以理解为祖先组件提供(Provide)
状态信息供后代组件消费(Consume)
,并且祖先和后代的状态信息可以实现双向同步。
注意:
@Provide
装饰变量必须进行本地初始化,而@Consume
装饰的变量不允许进行本地初始化。另外,@Provide
和@Consume
装饰的变量不是通过父组件向子组件传参的方式进行绑定的,而是通过相同的变量名进行绑定的。具体语法如下
祖先组件
@Entry
@Component
struct GrandParent {
@Provide count: number = 1;
build() {
Column() {
Parent()
}
}
}
父组件
@Component
struct Parent {
build() {
Column() {
Child()
}
}
}
子组件
@Component
struct Child {
@Consume count:number;
build() {
Column() {
Text(this.count.toString());
}
}
}
除了通过变量名进行绑定,还可通过变量的别名进行绑定,具体语法如下:
祖先组件
@Entry
@Component
struct GrandParent {
@Provide('count') parentCount: number = 1;
build() {
Column() {
Parent()
}
}
}
父组件
@Component
struct Parent {
build() {
Column() {
Child()
}
}
}
子组件
@Component
struct Child {
@Consume('count') childCount:number;
build() {
Column() {
Text(this.count.toString());
}
}
}
二、状态管理深入
2.1 @State
2.1.1 允许装饰的类型
@State
允许装饰的变量类型有string
、number
、boolean
、object
、class
和enum
类型,以及这些类型的数组
2.1.2 框架能够观察到的变化
并不是@State
状态变量的所有更改都会引起UI
的刷新,只有可以被框架观察到的修改才会引起UI刷新。能被框架观察到的变化如下
2.1.2.1 boolean、string、number类型
当@State
装饰的变量类型为boolean
、string
、number
类型时,可以观察
到赋值的变化
例如
//状态变量定义
@State count:number = 1;
//状态变量操作
this.count++; //可以观察到
2.1.2.2 class、object类型
当@State
装饰的变量类型为class
或者object
时,可以观察到变量自身赋值的变化,和其属性赋值的变化。需要注意的是,若某个属性也为 class
或者 object
,则嵌套属性的变化是观察不到的。
例如
//类型定义
class Employee {
name: string;
age: number;
job: Job;
constructor(name: string, age: number, job: Job) {
this.name = name;
this.age = age;
this.job = job;
}
}
class Job {
name: string;
salary: number;
constructor(name: string, salary: number) {
this.name = name;
this.salary = salary;
}
}
//状态定义
@State employee: Employee = new Employee('张三', 28, new Job('销售', 8000))
//状态操作
employee = new Employee('李四', 26, new Job('行政', 6000))//状态变量重新赋值,可以观察到
employee.age++;//修改状态变量的属性,可以观察到
employee.job.salary++;//修改状态变量的属性的属性,不可以观察到
2.1.2.3 数组类型
当@State
装饰的变量类型为数组时,可以观察到数组本身赋值的变化,和其元素的添加、删除及更新的变化,若元素类型为 class
或者 object
时,元素属性的变化,是观察不到的。
例如
//类型定义
export class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
//状态定义
@State persons: Person[] = [new Person('张三', 19), new Person('李四', 20)];
//状态操作
persons = [];//状态变量重新赋值,可以观察到
persons.push(new Person('王五',21));//新增数组元素,可以观察到
persons[0]=new Person('张三',22);//对数组元素重新赋值,可以观察到
persons[1].age++;//修改数组元素的属性,不可以观察到
2.1.2.4 总结
对于class
、object
和数组类型,框架仅能观察到@State
变量第一层属性的变化,例如employee.age++
,persons[0]=new Person('张三',22)
,但第二层属性的变化是观察不到的,例如employee.job.salary++
和persons[1].age++
。
2.2 @Prop
2.2.1 允许装饰的类型
@Prop
允许装饰的变量类型有string
、number
、boolean
、enum
,注意不支持class
、object
和数组
。
框架能够观察到的变化
2.2.2 框架能够观察到的变化
当装饰的类型是允许的类型,即string、number、boolean、enum类型时,所有赋值的变化都可以观察到。
2.3 @Link
2.3.1 允许装饰的类型(同@State
)
@Link允许装饰的变量类型有string、number、boolean、object、class和enum类型,以及这些类型的数组。
2.3.2 框架能够观察到的变化(同@State)
- 当装饰的数据类型为
boolean
、string
、number
类型时,可以观察到数值的变化。 - 当装饰的数据类型为
class
或者object
时,可以观察到变量自身赋值的变化,和其属性赋值的变化。需要注意的是,若某个属性也为class
或者object
,则嵌套属性的变化是观察不到的。 - 当装饰的数据类型为数组时,可以可以观察到数组本身赋值的变化,和其元素的添加、删除及更新的变化,若元素类型为
class
或者object
时,元素属性的变化,是观察不到的。
2.4 @Provide 和 @Consume
2.4.1 允许装饰的类型(同@State
)
@Provide
和@Consume
允许装饰的变量类型有string
、number
、boolean
、object
、class
和enum
类型,以及这些类型的数组。
2.4.2 框架能够观察到的变化(同@State
)
- 当装饰的数据类型为
boolean
、string
、number
类型时,可以观察到数值的变化 - 当装饰的数据类型为
class
或者objec
t时,可以观察到变量自身赋值的变化,和其属性赋值的变化。需要注意的是,若某个属性也为class
或者object
,则嵌套属性的变化是观察不到的。 - 当装饰的数据类型为数组时,可以可以观察到数组本身赋值的变化,和其元素的添加、删除及更新的变化,若元素类型为
class
或者object
时,元素属性的变化,是观察不到的。
2.5 @ObjectLink 和 @Observed
前文所述的装饰器都仅能观察到状态变量第一层的变化,而第二层的变化是观察不到的。如需观察到这些状态变量第二层的变化,则需要用到@ObjectLink
和@Observed
装饰器。
具体用法为:
- 将第二层内容抽取为一个子组件,并将第二层的数据作为子组件的状态变量,该变量需要使用
@ObjectLink
装饰。 - 第二层数据的类定义需要使用
@Observed
装饰器进行装饰。
@Observed
export class Job {
name: string;
salary: number;
constructor(name: string, salary: number) {
this.name = name;
this.salary = salary;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。