鸿蒙入门06-常见装饰器( 简朴装饰器 )
[*]装饰器是鸿蒙开辟中非常重要的一个环节
[*]因为在很多地方我们都必要用到装饰器
[*]并且假如我们想高度的复用, 那么装饰器就是必不可少的一环
[*]接下来我们就来介绍一些常见的装饰器
[*]留意 : 全部装饰器首字母大写
@Entry
[*]用来装饰 struct 利用
[*]体现页面的入口
@Component
[*]装饰 struct, 体现该 struct 具有基于组件的能力
[*]包管 struct 内部 包含一个且只能包含一个 build() 函数, 用于绘制 UI 界面
[*]struct 内部, build() 函数外部, 用于存储数据的位置
[*]留意 : build() 函数内部必须要有容器组件
@Entry
@Component
struct Index {
/* 这里存放数据 */
build() {
/* 这里构建 UI 界面 */
}
} 以上为基础内容布局
[*]@Component 也可以单独界说组件
[*]单独界说的组件可以在其他组件内利用
@Entry
@Component
struct Index {
/* 这里存放数据 */
build() {
/* 这里构建 UI 界面 */
Row() {
/* 可以直接使用子组件 */
SonCom()
}
}
}
// 定义一个子组件
@Component
struct SonCom {
build() {
/* 这里构建子组件 UI 结构 */
}
} @State
[*]用来装饰变量的装饰器( 其实就是用于界说变量 )
[*]必须本地初始化数据, 支持通过构造函数赋值
[*]当 @State 界说的数据被修改的时候, 地点组件的 build() 方法会被重新调用, 重新绘制地点 UI 界面
@Entry
@Component
struct Index {
/* 这里存放数据 */
@State count: number = 0
build() {
/* 这里构建 UI 界面 */
Column() {
// 展示 @state 定义的变量
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
// 按钮点击的时候修改 @state 定义的变量
Button('Click Me').onClick(() => this.count++)
}
}
} https://i-blog.csdnimg.cn/blog_migrate/51b4bb4385e75bf18d561f1837234551.png
这里利用 Text() 组件展示了 @State 界说的 count 变量
通过 Button() 组件的点击事件修改了 @State 界说的 count 变量
因为变量的修改导致了 UI 界面的重新绘制
所以页面跟随出现变革
其实就是我们之前知道的响应式数据一个原理
[*]在子组件内也同样是利用 @State 界说数据
[*]在子组件内界说的数据, 可以通过父组件调用的时候进行赋值
@Entry
@Component
struct Index {
/* 这里存放数据 */
@State count: number = 0
build() {
/* 这里构建 UI 界面 */
Column() {
Text('父组件 UI 部分').fontSize(20)
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me').onClick(() => this.count++)
Blank().height(30)
Text('子组件 UI 部分')
SonCom() // 不对初始内容进行赋值
Blank().height(30)
Text('子组件 UI 部分')
SonCom({ count: 100 }) // 对初始内容进行赋值
}
}
}
@Component
struct SonCom {
@State count: number = 0
build() {
Column() {
Text(`${ this.count }`).fontSize(20)
}
}
} https://i-blog.csdnimg.cn/blog_migrate/bb76408b135192ee7f3addf8a1c9320f.png
当你调用子组件的时候
假如不对 @State 界说的变量赋值, 那么就用子组件内初始化时候的赋值
假如对 @State 界说的变量赋值, 那么就会利用调用时所赋予的值
[*]通过 @State 在子组件内进行赋值
[*]父子组件是互不干扰的, 数据是相互独立的
@Entry
@Component
struct Index {
/* 这里存放数据 */
@State count: number = 0
build() {
/* 这里构建 UI 界面 */
Column() {
Text('父组件 UI 部分').fontSize(20)
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改父组件 count').onClick(() => this.count++)
Blank().height(30)
Text('子组件 UI 部分')
SonCom()
}
}
}
@Component
struct SonCom {
@State count: number = 0
build() {
Column() {
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改子组件 count').onClick(() => this.count++)
}
}
} https://i-blog.csdnimg.cn/blog_migrate/11c34515a003f60035faa3343466c2fb.png
@Prop
[*]继承了 @State 的全部功能
[*]留意 :
[*]
[*]界说的时候可以不必要本地直接初始化, 调用子组件的时候必要对其进行赋值
[*]被 @Prop 装饰的变量可以和父组件建立单向同步关系
[*]@Prop 装饰的变量是可变的, 但是修改时不会同步回父组件, 当父组件的 @State 变革时, 本地修改的 @Prop 会被覆盖
@Entry
@Component
struct Index {
/* 这里存放数据 */
@State count: number = 0
build() {
/* 这里构建 UI 界面 */
Column() {
Text('父组件 UI 部分').fontSize(20)
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改父组件 count').onClick(() => this.count++)
Blank().height(30)
Text('子组件 UI 部分')
// 调用自组件的时候, 将父组件 @State 定义的 count 赋值
SonCom({ count: this.count })
}
}
}
@Component
struct SonCom {
// 使用 @Prop 定义一个初始变量
@Prop count: number
build() {
Column() {
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改子组件 count').onClick(() => this.count++)
}
}
} https://i-blog.csdnimg.cn/blog_migrate/d02d0d6053743e9487cda0b1cf8b353b.png
[*]此时, 当你在子组件内修改 count 的时候, 子组件内的数据单独出现变换
[*]但是当你在父组件内修改 count 的时候, 会连带修改子组件内的 count, 并且会将覆盖子组件内的修改
https://i-blog.csdnimg.cn/blog_migrate/fc039aefaefd000db805ff9a06b9ea58.png
@Link
[*]@Link 装饰的变量和父组件会构建双向同步关系
[*]
[*]父组件会担当来自 @Link 装饰的变量的修改同步
[*]父组件的更新也会同步给 @Link 装饰的变量
[*]@Link 装饰的变量与其父组件中的数据源共享相同的值
[*]留意 :
[*]
[*]子组件利用 @Link 界说变量的时候不必要赋值, 而是调用子组件的时候进行赋值
[*]调用子组件赋值的时候利用 "$变量名" 的情势进行赋值
[*]@Link 装饰器不能再 @Entry 装饰的自界说组件中利用
@Entry
@Component
struct Index {
/* 这里存放数据 */
@State count: number = 0
build() {
/* 这里构建 UI 界面 */
Column() {
Text('父组件 UI 部分').fontSize(20)
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改父组件 count').onClick(() => this.count++)
Blank().height(30)
Text('子组件 UI 部分')
// 调用自组件的时候, 将父组件 @State 定义的 count 赋值
// 注意: 使用 $变量名 的形式进行赋值
SonCom({ count: $count })
}
}
}
@Component
struct SonCom {
// 使用 @Link 定义一个初始变量
@Link count: number
build() {
Column() {
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改子组件 count').onClick(() => this.count++)
}
}
} https://i-blog.csdnimg.cn/blog_migrate/d09615901067096886a162a203e3f12d.png
[*]此时, 子组件内修改 count 的时候, 会同步影响到父组件内的 count
[*]修改父组件内的 count 的时候, 也会同步影响到子组件内的 count
https://i-blog.csdnimg.cn/blog_migrate/05256909fc6b8bab57e737cf9efeb7f0.png
@Provide 和 @Consume
[*]之前我们学习过了 @State/@Link 两个装饰器组合在一起, 可以实现父子组件的双向数据传递
[*]假如在父子组件之间进行数据传递的话, 利用起来照旧相当方便的
[*]但是, 假如层级过高的话, 那么利用起来就比力贫苦来
[*]我们先来看一下 @State/@Link 进行层级组件嵌套
@Entry
@Component
struct Index {
/* 这里存放数据 */
@State count: number = 0
build() {
Column() {
Text('父组件 UI 部分').fontSize(20)
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改父组件 count').onClick(() => this.count++)
Blank().height(30)
Text('子组件 UI 部分')
// 调用子组件的时候, 将父组件 @State 定义的 count 赋值
// 注意: 使用 $变量名 的形式进行赋值
SonCom({ count: $count })
}
}
}
@Component
struct SonCom {
// 使用 @Link 定义一个初始变量
@Link count: number
build() {
Column() {
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改子组件 count').onClick(() => this.count++)
Blank().height(30)
Text('子子组件 UI 部分')
// 调用子子组件的时候, 将子组件 @Link 定义的 count 赋值
// 注意: 使用 $变量名 的形式进行赋值
SonSonCom({ count: $count })
}
}
}
@Component
struct SonSonCom {
// 使用 @Link 定义一个初始变量
@Link count: number
build() {
Column() {
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改子组件 count').onClick(() => this.count++)
}
}
} https://i-blog.csdnimg.cn/blog_migrate/467e0ef025f7347b989d5fad07e6984e.png
[*]此时我们就实现了跨组件传递数据
[*]但是想对来说就比力贫苦了, 相当繁琐
[*]假如组件嵌套的层级过深, 那么这个数据的传递就着实是太复杂了
[*]此时我们可以利用 @Provide 和 @Consume 进行跨组件数据传递
[*]利用语法 :
[*]
[*]@Provide('名字') 变量名: 类型 = 赋值
[*]@Consume('名字') 变量名
[*]留意 : @Provide 和 @Comsume 处利用的名字要同等, 但是变量名不必要同等
https://i-blog.csdnimg.cn/blog_migrate/2a9e4e3863159c6d6d733428013c88a2.png
https://i-blog.csdnimg.cn/blog_migrate/df1de0edf931c192de72167af5244e41.png
[*]利用发布订阅模式, 父类利用 @Provide, 其他必要观察的子类利用 @Consume, 就可以实现双向绑定
[*]当层级很深时, 不必要一层一层传递数据, 直接利用发布订阅进行监听就能实现相同的效果
[*]@Provide 和 @Consume 可以通过相同的变量名或者相同的变量别名绑定, 但是变量类型必须相同
[*]@Provide 必须设置初始值, @Consume 不可以设置默认初始值
[*]@Provide 修饰的变量和 @Consume 修饰的变量可以是一对多的关系
@Watch
[*]利用观察者模式的装饰器
[*]留意 : 该装饰器不是触发变量变革, 而是绑定一个函数, 当监控的变量发生变革时, 该函数触发
[*]语法 : @Watch('函数名')
@Entry
@Component
struct Index {
/* 这里存放数据 */
// 在父组件内使用 @Provide 创建数据
@State count: number = 0
build() {
Column() {
Text('父组件 UI 部分').fontSize(20)
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改父组件 count').onClick(() => this.count++)
Blank().height(30)
Text('子组件 UI 部分')
SonCom({ count: this.count })
}
}
}
@Component
struct SonCom {
@Prop @Watch('onCountUpdate') count: number
onCountUpdate(): void {
console.log('count 数据发生变化了')
}
build() {
Column() {
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改父组件 count').onClick(() => this.count++)
}
}
} https://i-blog.csdnimg.cn/blog_migrate/2337341168bb5927f46e58bcb1945a24.png
https://i-blog.csdnimg.cn/blog_migrate/e22c76b10b4b09a9f85b58cba350e4c6.png
@Builder
[*]@Builder 是 ArkUI 提供的一种更加轻量的复用机制
[*]因为在 @Component 内能且只能创建一个 build() 函数
[*]我们可以在组件内利用 @Builder 装饰器自界说一个构建函数
[*]@Builder 创建的构建函数遵循 build() 函数的语法规则, 并且可以在 build() 函数内调用
[*]语法 :
[*]
[*]界说语法 : @Builder MyBuilder() {}
[*]利用语法 : this.MyBuilder() {}
[*]语法要点
[*]
[*]自界说构建函数可以在所属组件内的 build() 方法和其他自界说构建函数内调佣, 但不答应在组件外调用
[*]答应在自界说组件内界说一个或多个 @Builder 方法, 该方法被以为是该组件的私有成员
[*]在自界说函数体内, this 指代当前所属组件, 组件的状态变量可以在自界说构建函数内访问
[*]自界说构建函数不仅可以添加属性, 还可以添加事件
https://i-blog.csdnimg.cn/blog_migrate/3137a43605dd7915c213b7933c1a83d0.png
[*]在组件外也可以利用 @Builder 创建一个自界说构建函数
[*]留意 : 在组件外利用 @Builder 的时候, 构建函数内不能利用 this
@Entry
@Component
struct Index {
/* 这里存放数据 */
// 在父组件内使用 @Provide 创建数据
@State count: number = 0
// 创建一段组件内自定义构建函数
@Builder CountUpdate() {
Text('父组件 UI 部分').fontSize(20)
Text(`${ this.count }`).fontSize(20)
Divider().margin(10)
Button('Click Me 修改父组件 count').onClick(() => this.count++)
}
build() {
Column() {
// 直接使用自定义构建函数
this.CountUpdate()
Blank().height(30)
// 使用组件外自定义构建函数
MyBuilder('Hello World')
}
}
}
// 组件外定义自定义构建函数
@Builder
function MyBuilder(message: string) {
Column() {
Text(message)
}
} https://i-blog.csdnimg.cn/blog_migrate/ae4bdd995ac353df3722b4d22f28bd95.png
@Styles
[*]在开辟中有的时候, 有的时候我们的一些样式也要重用
[*]@Styles 装饰器就可以将多条样式提炼成一个方法, 以供复用
[*]和 @Builder 一样, 可以界说在 组件内 和 组件外
@Entry
@Component
struct Index {
// 定义一个组件内样式方法
@Styles MyStyles() {
.width(200)
.height(200)
.backgroundColor(Color.Orange)
}
build() {
Column() {
Row() {}.MyStyles()
Blank().margin(10)
Row() {}.MyStyles()
}
}
} https://i-blog.csdnimg.cn/blog_migrate/3065269d502861c71fed14d116805a7f.png
[*]这是组件内界说样式方法
[*]我们再来界说一个组件外样式方法
@Entry
@Component
struct Index {
// 定义一个组件内样式方法
@Styles MyStyles() {
.width(200)
.height(200)
.backgroundColor(Color.Orange)
}
build() {
Column() {
Row() {}.MyStyles()
Blank().margin(10)
Row() {}.MyStyles2()
}
}
}
@Styles
function MyStyles2() {
.width(100)
.height(100)
.backgroundColor(Color.Pink)
} https://i-blog.csdnimg.cn/blog_migrate/11a6ffb5321c66e874002e12478bac1e.png
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]