赞
踩
目录
组件编程在使用过程中有很多技巧,在这里分享样式复用技巧和UI结构复用技巧。
我们观察下面的代码,在代码中很多重复行的代码,如:
Image 的 .width(30).height(30) 是重复的 Button的 .fontSize(25).width(150).height(65).backgroundColor(Color.Green)是重复的 Text 的 .fontSize(20).fontColor(Color.White).fontWeight(500) 是重复的
- @Entry
- @Component
- struct customStyle {
- @State isOn: boolean = false;
- @State isDel: boolean = false;
-
- build() {
- Column({ space: 10 }) {
- Button({ type: ButtonType.Capsule, stateEffect: true }) {
- Row({ space: 10 }) {
- Image($r('app.media.icon_new_folder'))
- .width(30)
- .height(30)
- Text('新建文件')
- .fontSize(20)
- .fontColor(Color.White)
- .fontWeight(500)
- }
- }
- .fontSize(25)
- .width(150)
- .height(65)
- .backgroundColor(Color.Green)
- .onClick(() => {
- console.log('我准备开始建立文件夹');
- })
-
- Button({ type: ButtonType.Capsule, stateEffect: true }) {
- Row({ space: 10 }) {
- Image($r('app.media.icon_new_folder'))
- .width(30)
- .height(30)
- Text('新建文件')
- .fontSize(20)
- .fontColor(Color.White)
- .fontWeight(500)
- }
- }
- .fontSize(25)
- .width(150)
- .height(65)
- .backgroundColor(Color.Green)
- .onClick(() => {
- console.log('我准备开始建立文件夹');
- })
- }
- .width('100%')
- .height("100%")
- .justifyContent(FlexAlign.Center)
-
- }
- }
-
-
- @Extend(Image) function consumeImgStyle() {
- .width(30)
- .height(30)
- }
-
- @Extend(Button) function consumeButtonStyle() {
- .fontSize(25)
- .width(150)
- .height(65)
- }
-
- @Extend(Text) function consumeBTextStyle() {
- .fontSize(20)
- .fontColor(Color.White)
- .fontWeight(500)
- }

当多个组件具有相同的样式时,若每个组件都单独设置,将会有大量的重复代码。为避免重复代码,开发者可使用@Styles或者@Extend装饰器将多条样式设置提炼成一个方法,然后直接在各组件声明的位置进行调用,这样就能完成样式的复用。
@Styles方法可定义在组件内或者全局。
将上面重复的样式代码分别提取到各自定义的@Style方法中,直接使用@Style方法
定义格式如下。
- @Styles定义在Struct结构体内部
- ===============================================================================
- @Styles consumeImgStyle(){
- .width(30)
- .height(30)
- }
-
- @Styles consumeButtonStyle(){
- .width(150)
- .height(65)
- .backgroundColor(Color.Green)
- }
-
- @Styles定义在同一个ets文件中的Struct结构体外部,必须加上 function 关键字
- ===============================================================================
-
- @Styles function globalConsumeImgStyle() {
- .width(30)
- .height(30)
- }
-
- @Styles function globalConsumeButtonStyle() {
- .width(150)
- .height(65)
- .backgroundColor(Color.Green)
- }

将重复样式代码提取之后,直接使用提取后的方法,使用@Styles方法之后代码。
- @Entry
- @Component
- struct customStyle {
- @State isOn: boolean = false;
- @State isDel: boolean = false;
-
- build() {
- Column({ space: 10 }) {
- Button({ type: ButtonType.Capsule, stateEffect: true }) {
- Row({ space: 10 }) {
- Image($r('app.media.icon_delete'))
- .consumeImgStyle()
- Text('删除文件')
- .fontSize(20)
- .fontColor(Color.White)
- .fontWeight(500)
- }
- }
- .fontSize(25)
- .width(150)
- .height(65)
-
- Button({ type: ButtonType.Capsule, stateEffect: true }) {
- Row({ space: 10 }) {
- Image($r('app.media.icon_new_folder'))
- .consumeImgStyle()
- Text('新建文件')
- .fontSize(20)
- .fontColor(Color.White)
- .fontWeight(500)
- }
- }
- .consumeButtonStyle()
- .fontSize(25)
- .onClick(() => {
- console.log('我准备开始建立文件夹');
- })
- }
- .width('100%')
- .height("100%")
- .justifyContent(FlexAlign.Center)
-
- }
-
- @Styles consumeImgStyle(){
- .width(30)
- .height(30)
- }
-
- @Styles consumeButtonStyle(){
- .width(150)
- .height(65)
- .backgroundColor(Color.Green)
- }
- }
-
- 定义全局使用的@Styles方法需要加 function
- ======================================================
- @Styles function globalConsumeImgStyle() {
- .width(30)
- .height(30)
- }
-
- @Styles function globalConsumeButtonStyle() {
- .width(150)
- .height(65)
- .backgroundColor(Color.Green)
- }

@Extend装饰的方法同样可用于组件样式的复用,与@Styles不同的是:
重复的代码
Image 的 .width(30).height(30) 是重复的
Button的 .fontSize(25).width(150).height(65) .backgroundColor(Color.Green)是重复的
Text 的 .fontSize(20).fontColor(Color.White).fontWeight(500)是重复的
将上面重复的样式代码分别提取到各自定义的@Extend方法中,直接使用@Extend方法
定义格式如下。
- @Extend(Image) function consumeImgStyle() {
- .width(30)
- .height(30)
- }
-
- @Extend(Button) function consumeButtonStyle(color: Color) {
- .fontSize(25)
- .width(150)
- .height(65)
- .backgroundColor(color)
-
- }
-
- @Extend(Text) function consumeTextStyle(color: Color, size: number, weight: number) {
- .fontSize(size)
- .fontColor(color)
- .fontWeight(weight)
- }

将重复样式代码提取之后,直接使用提取后的方法,使用@Extend方法之后代码。
- @Entry
- @Component
- struct customStyle {
- @State isOn: boolean = false;
- @State isDel: boolean = false;
-
- build() {
- Column({ space: 10 }) {
- Button({ type: ButtonType.Capsule, stateEffect: true }) {
- Row({ space: 10 }) {
- Image($r('app.media.icon_new_folder'))
- .consumeImgStyle()
- Text('新建文件')
- .consumeTextStyle(Color.White, 20, 500)
- }
- }
- .consumeButtonStyle(Color.Green)
- .onClick(() => {
- console.log('我准备开始建立文件夹');
- })
-
- Button({ type: ButtonType.Capsule, stateEffect: true }) {
- Row({ space: 10 }) {
- Image($r('app.media.icon_new_folder'))
- .consumeImgStyle()
- Text('新建文件')
- .consumeTextStyle(Color.White, 20, 500)
- }
- }
- .consumeButtonStyle(Color.Green)
- .onClick(() => {
- console.log('我准备开始建立文件夹');
- })
- }
- .width('100%')
- .height("100%")
- .justifyContent(FlexAlign.Center)
- }
- }
-
-
- @Extend(Image) function consumeImgStyle() {
- .width(30)
- .height(30)
- }
-
- @Extend(Button) function consumeButtonStyle(color: Color) {
- .fontSize(25)
- .width(150)
- .height(65)
- .backgroundColor(color)
-
- }
-
- @Extend(Text) function consumeTextStyle(color: Color, size: number, weight: number) {
- .fontSize(size)
- .fontColor(color)
- .fontWeight(weight)
- }

当页面有多个相同的UI结构时,若每个都单独声明,同样会有大量重复的代码。为避免重复代码,可以将相同的UI结构提炼为一个自定义组件,完成UI结构的复用。
除此之外,ArkTS还提供了一种更轻量的UI结构复用机制@Builder方法,开发者可以将重复使用的UI元素抽象成一个@Builder方法,该方法可在build()方法中调用多次,以完成UI结构的复用。
@Builder装饰的方法同样可用于组件接结构的复用,
- @Entry
- @Component
- struct BuilderUI {
- @State isOn: boolean = false;
- @State isDel: boolean = false;
-
- build() {
- Column({ space: 10 }) {
- this.builderButton($r('app.media.icon_delete'), '删除文件', () => {
- console.log('我准备开始删除文件夹');
- })
- globalBuilderButton($r('app.media.icon_new_folder'), '新建文件', () => {
- console.log('我准备开始建立文件夹');
- })
- }
- .width('100%')
- .height("100%")
- .justifyContent(FlexAlign.Center)
- }
-
- @Builder builderButton(icon: Resource, text: string, callback: () => void) {
- Button({ type: ButtonType.Capsule, stateEffect: true }) {
- Row({ space: 10 }) {
- Image(icon)
- .width(30)
- .height(30)
- Text(text)
- .fontSize(20)
- .fontColor(Color.White)
- .fontWeight(500)
- .backgroundColor(Color.Green)
- }
- }
- .fontSize(25)
- .width(150)
- .height(65)
- .onClick(callback)
- }
- }
-
- @Builder function globalBuilderButton(icon: Resource, text: string, callback: () => void) {
- Button({ type: ButtonType.Capsule, stateEffect: true }) {
- Row({ space: 10 }) {
- Image(icon)
- .width(30)
- .height(30)
- Text(text)
- .fontSize(20)
- .fontColor(Color.White)
- .fontWeight(500)
- .backgroundColor(Color.Green)
- }
- }
- .fontSize(25)
- .width(150)
- .height(65)
- .onClick(callback)
- }

- @Entry
- @Component
- struct BuilderUI {
- @State status: number = 10;
-
- build() {
- Column({ space: 10 }) {
- valueText(this.status)
- referenceText({status:this.status})
-
- Row({ space: 10 }) {
- Button('值传递 - 1')
- .consumeButtonStyle()
- .onClick(() => {
- this.status--
- })
- Button('引用传递 + 1')
- .consumeButtonStyle()
- .onClick(() => {
- this.status++
- })
- }
- }
- .width('100%')
- .height("100%")
- .justifyContent(FlexAlign.Center)
- }
-
-
- }
-
- @Builder function valueText(count: number) {
- Text(`进行值传递: ${count}`).fontSize(30).fontWeight(600)
- }
-
- @Builder function referenceText(count: {status:number}) {
- Text(`进行引用传递: ${count.status}`).fontSize(30).fontWeight(600)
- Text('引用参数传递的是状态变量status,这里内部UI会刷新')
- }
-
- @Extend(Button) function consumeButtonStyle() {
- .fontSize(20)
- .width(140)
- .height(65)
- }
-
-

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。