前言
并不是状态变量的所有更改都会引起UI的刷新,只有可以被框架监听到的修改才会引起UI刷新。下面会对对应的装饰器进行简单的测试,确认那种数据是可以被监听的。
装饰器@State
定义(装饰)变量,绑定该变量的UI会随着变量值的变化而变化,支持当前变量修改以及第一层数据的修改的监听,属于是浅监听
●装饰普通数据类型数据,修改数据都是可以正常监听的
●装饰Object类型数据,支持当前变量修改以及第一层数据的修改的监听,如下当只修改this.obj.sub.b的值是UI不会发生改变,经过打印数据已经被修改成功。
interface ObjT {
a?:string,
sub: {
b:string
}
}
@Entry
@Component
struct Index {
@State obj: ObjT = {
a:'1',
sub: {
b: '1'
}
}
build() {
Row() {
Column() {
Button(`按钮${this.obj.a}${this.obj.sub.b}`)
.onClick(() => {
this.obj.sub.b = '-'
this.obj.a = '2'
})
}
.width('100%')
}
.height('100%')
}
}
●装饰的对象是array时,可以观察到数组本身的赋值和添加、删除、更新数组的变化。但是数组单项里面的数据发生改变的时候不会被监听到。
●装饰class对象类型的变量时,可以观察到自身的赋值的变化,和其属性赋值的变化。但不支持嵌套的属性赋值观察不到。
class ClassA {
public value: string;
constructor(value: string) {
this.value = value;
}
}
class Model {
public value: string;
public name: ClassA;
constructor(value: string, a: ClassA) {
this.value = value;
this.name = a;
}
}
@State title: Model = new Model('Hello', new ClassA('World'));
// 可以被监听
this.title.value = 'Hi';
// 嵌套的属性赋值观察不到
this.title.name.value = 'ArkUI';
装饰器@Prop
定义(装饰)从父组件传入当前组件的变量,单向数据流即父组件变量变化会影响到当前变量,当前变量也可以单独修改但是变化不会同步回其父组件。
@Component
struct Sec {
@Prop msg:string //接收父组件message变量
build() {
Button(this.msg)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.msg = '2222' // 修改当前组件数据,父组件数据不会改变
})
}
}
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Button(`按钮${this.message}`)
.onClick(() => {
this.message = '8888' //修改会同步子组件
})
Sec({msg: this.message})
}
}
}
}
装饰器@Link
使用同@Prop,特点是可以父子双向同步,传值的方式稍微不同需要是$开头
@Component
struct Sec {
@Link msg:string //接收父组件message变量
build() {
Button(this.msg)
.fontSize(50)
.fontWeight(FontWeight.Bold)
.onClick(() => {
this.msg = '2222' //修改会同步父组件
})
}
}
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Button(`按钮${this.message}`)
.onClick(() => {
this.message = '8888' //修改会同步子组件
})
Sec({msg: $message}) // 传值是需是$开头
}
}
}
}
装饰器@Provide与@Consume
前端童鞋对这个东西应该很熟悉🤭。上面@Prop与@Link用于父子组件传值。@Provide与@Consume组合是用来后代组件双向同步的,简单说就是不仅支持父子组件,还支持爷孙组件,祖孙组件。。。
使用起来很简单,在上级组件@Provide定义变量,且不需要一直向下传递,哪里需要哪里使用@Consume接收就行。
@Component
struct Sec {
build() {
Three()
}
}
@Component
struct Three {
@Consume message: string; // 接收Provide传递的数据
build() {
Column() {
Text('2222')
.fontSize(50)
.fontWeight(FontWeight.Bold)
Button(this.message)
.fontSize(50)
.onClick(() => {
this.message = '2222' // 孙组件修改并同步祖父组件
})
}
}
}
@Entry
@Component
struct Index {
@Provide message: string = 'Hello World' // 定义需要传递的变量,不需要一直传递,那个下级组件需要在哪里接数据就行
build() {
Row() {
Column() {
Button(`按钮${this.message}`)
.onClick(() => {
this.message = '8888' // 祖父组件修改并同步孙组件
})
Sec()
}
.width('100%')
}
.height('100%')
}
}
装饰器@Observed@ObjectLink
了解@State装饰器的时候,发现数据监听只会监听修改自己和第一层的变化,如果需要监听深层数据的话就需要用到这俩装饰器。在使用过程中发现,灵活度不高(也可能之前一直在用js),感觉写法比较死板。
首先官方给给出以下两个限制:
●使用@Observed装饰class会改变class原始的原型链,@Observed和其他类装饰器装饰同一个class可能会带来问题。
●@ObjectLink装饰器不能在@Entry装饰的自定义组件中使用。
首先测试一下深层监听,不能用在注意入口组件而且不能直接初始化数据
写在最后
有很多小伙伴不知道该从哪里开始学习鸿蒙开发技术?也不知道鸿蒙开发的知识点重点掌握的又有哪些?自学时频繁踩坑,导致浪费大量时间。结果还是一知半解。所以有一份实用的鸿蒙(HarmonyOS NEXT)全栈开发资料用来跟着学习是非常有必要的。
获取完整版高清学习资料,请点击→鸿蒙全栈开发学习资料(安全链接,请放心点击)
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了
最新鸿蒙全栈开发学习线路
鸿蒙HarmonyOS开发教学视频