OpenHarmony ETS 掌握组件化这些装饰器写好界面事半功倍 原创 精华
陈浩南xxx
发布于 2022-4-24 14:18
浏览
3收藏
OpenHarmony ETS 掌握组件化这些装饰器写好界面事半功倍
水之积也不厚,则其负大舟也无力
前言:写这篇文章的目的性,是让新手了解几个装饰器的作用,知道如何更加的使得代码模块化,复用性更高,提升代码的阅读效率。
1,@Entry
- @Entry装饰的@Component为页面的==总入口==,一个页面==有且仅有一个==@Entry
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
Api9下的注册方式
2,@Component
UI都是通过@Component声明来修饰,如下
- 所有的UI都是由组件构成,组件的数据结构为struct
- @Component==装饰struct==,使之成为自定义组件,
- 自定义组件可以调用其他自定义组件和内置组件
- 自定义组件内部==必须实现build方法==来描述UI结构
- 禁止自定义构造函数
3,@Preview
- ==单组件预览==,无视@Entry装饰器,仅预览被@Preview装饰的自定义组件
- 在单个源文件中,==最多==可以使用**@Preview**==装饰一个自定义组件==
我们在预览无Entry修饰的组件时
于是我们可以用@Preview来预览效果
4,@Builder
-
@Builder装饰器定义了一个如何==渲染自定义组件的方法==,语法和作用和build函数一致。
-
通过@Builder装饰器可以在一个==自定义组件内==快速生成多个布局内容
这样的好处就是可以减少大量重复的代码,还能逻辑统一,一处修改多UI生效
@Entry
@Component
struct Index {
@State message: string = 'Builder演示'
@State isA: boolean= false
@State isB: boolean= false
@State isC: boolean= false
@State isD: boolean= false
/* 方法内有组件,需要加@Builder装饰 */
@Builder myBuilder(str: string, state: boolean, click: () => void) {
Row() {
Text(str + ":" + state)
.fontSize(24).margin({ right: 20 })
Button('开关').fontSize(24).onClick(() => {
click()
})
}
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(24)
.fontWeight(FontWeight.Bold).margin({ bottom: 20 })
this.myBuilder('A', this.isA, () => {
this.isA = !this.isA
})
this.myBuilder('B', this.isB, () => {
this.isB = !this.isB
})
this.myBuilder('C', this.isC, () => {
this.isC = !this.isC
})
this.myBuilder('D', this.isD, () => {
this.isD = !this.isD
})
}
.width('100%')
}
.height('100%')
}
}
5,@Extend
-
==对内置组件进行二次封装==
-
@Extend装饰器不能用在自定义组件struct定义框内
模拟器测试报错,理论上是可以支持的
这样的优点可以减少对内置组件的重复设置,可以封装在一个方法内
@Extend(Text) function fancy (size: number, color: ResourceColor) {
.fontSize(size)
.fontColor(color)
}
@Entry
@Component
struct Index {
@State message: string = 'Extend演示'
build() {
Column() {
Text(this.message)
.fancy(24, Color.Blue)
}
}
}
6,@CustomDialog
- 用于装饰自定义弹窗。
@CustomDialog
struct CustomDialogExample {
controller: CustomDialogController
cancel: () => void
confirm: () => void
build() {
Column() {
Text('自定义弹窗').fontSize(20).margin({ top: 10, bottom: 10 })
Image($r('app.media.icon')).width(80).height(80)
Text('你确认要这样选择吗?').fontSize(16).margin({ top: 10, bottom: 10 })
Flex({ justifyContent: FlexAlign.SpaceAround }) {
Button('否')
.onClick(() => {
this.controller.close()
this.cancel()
}).backgroundColor(0xffffff).fontColor(Color.Black)
Button('是')
.onClick(() => {
this.controller.close()
this.confirm()
}).backgroundColor(0xffffff).fontColor(Color.Red)
}.margin({ bottom: 10 })
}
}
}
@Entry
@Component
struct CustomDialogUser {
@State text: string= ""
dialogController: CustomDialogController = new CustomDialogController({
builder: CustomDialogExample({ cancel: this.onCancel, confirm: this.onAccept }),
cancel: this.existApp,
autoCancel: true
})
onCancel() {
console.info('Callback when the first button is clicked')
this.text = '用户点击了取消'
}
onAccept() {
this.text = '用户点击了确认'
console.info('Callback when the second button is clicked')
}
existApp() {
console.info('Click the callback in the blank area')
this.text = '用户点击了空白处'
}
build() {
Column() {
Text(this.text).fontSize(24).margin({ top: 10 })
Button('打开弹窗').fontSize(24)
.onClick(() => {
this.dialogController.open()
})
}.width('100%').margin({ top: 10 })
}
}
注意:从效果看 @State修饰的变量,从@CustomDialog修饰的CustomDialogExample类,回调了该方法,但是它没有重新使得build刷新,
原因不明(==评论区有答案==)
7,@BuilderParam
可以在局部样式相同,局部样式不同是复用
@Component
struct CustomContainer {
title: string;
subTitle: string;
@BuilderParam content: () => any
build() {
Column() {
Text(this.title).fontSize(24).fontColor('#FF0000')
Text(this.subTitle).fontSize(18).fontColor('#0D9FFB')
this.content()
}
}
}
@Entry
@Component
export struct MainPage {
build() {
Column() {
Text('@BuilderParam演示')
.fontSize(24).margin({ top: 20 })
Column() {
CustomContainer({ title: '标题1', subTitle: '内容1' }) {
Row() {
Text('图文结合').fontSize(18)
Image($r('app.media.app_icon')).width(30).height(30)
}
}
}.margin({ top: 20 })
Column() {
CustomContainer({ title: '标题2', subTitle: '内容2' }) {
Row() {
Text('其他样式').fontSize(18)
Button('点击').fontSize(20)
}
}
}.margin({ top: 20 })
}
.height('100%')
.width('100%')
}
}
8,@Styles
-
@Styles装饰的方法不能带参数
-
组件内@Styles装饰的方法可以有多个
多个相同属性可以利用此装饰器封装
@Entry
@Component
struct Stylesdemo {
@State message: string = 'Hello World'
@Styles backgroundRed(){
.backgroundColor(Color.Red)
}
@Styles size100(){
.width(100)
.height(100)
}
build() {
Row() {
Column() {
Text(this.message)
.backgroundRed()
.fontSize(50)
.fontWeight(FontWeight.Bold)
Image($r('app.media.app_icon')).size100()
}
.width('100%')
}
.height('100%')
}
}
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
已于2022-4-25 14:49:30修改
赞
5
收藏 3
回复
相关推荐
没有刷新是this指向问题
这样写就可以了
果然可以,谢谢大佬指点; 想问下:bind(this)这个this是指的谁?
指向这个组件CustomDialogUser自己
其实等同于
cancel传递一个普通函数的时候,这个函数的上下文其实已经改变了,为了保证上下文还是CustomDialogUser,需要指定this的指向。
可以看看es6的箭头函数
https://www.liaoxuefeng.com/wiki/1022910821149312/1031549578462080