【HarmonyOS开发实战】鸿蒙UI通用代码几种抽离方法

前言

对于做APP的UI,免不了会写大量的重复布局,重复UI页面。此时对于将重复的UI控件抽离出来封装为通用组件来进行优化很是重要。
    
    本文重点分析鸿蒙几种UI处理上,如何抽离通用方法来进行UI的复用。重点对比@Style,@Extend, AttributeModifier, @Builder和 struct 这五种方法的区别和使用场景。

Styles装饰器

学过Android开发的小伙伴知道Android中有样式Style概念,我们定义好一个样式,那么就可以在各个组件中使用。从而保持每个组件有一样的属性。
    同理,鸿蒙中也可以使用样式。比如我们UI上的按钮具有相同的宽,高,背景色和边角距。那么我们就可以定义一个Style,每次定义按钮时候,只需要将Style赋给按钮就可以实现该属性,从而避免重复代码的书写。

●代码说明
●

如图,在当前页面内定义一个方法,使用装饰器Styles修饰,修饰后,方法内部就可以直接通过 .属性 的方式来定义属性了。方法定义完后,下方button里可以直接使用该方法。虽然我这里方法命名为commonButton,但是实际上所有基础控件都可以使用该方法使用里边的属性,比如下方的Text组件。

●Style特点

1.对于定义的方法,无法使用export修饰。
这也就意味着,我们抽离的通用属性,只能在当前页面内的组件上使用,换个页面就不可以了,无法做到全局所有页面通用。
2.对于定义的方法,只能定义组件的通用属性。
比如宽高,背景色等。对于一些控件特有属性是无法定义的。比如Select组件的selectedOptionFont特有属性无法定义。
3.方法不支持传递入参。
意味着该样式无法做到动态修改,只要定义好就无法修改。比如定义好宽高为30,而某个组件宽要求为40,其他属性都不变,那这个方法也没法用了。
4.方法为组件通用属性,故所有组件都可以引用方法。

Extend装饰器

对于Styles装饰器的第2点限制,鸿蒙推出了解决方案,那就是使用@Extend装饰器。
    Extend装饰器需要我们在使用时候指定定义哪个组件的属性,是专门抽离指定组件的。

●代码说明
在这里插入图片描述

Extend要求必须定义方法为在当前文件的全局定义,且也不能够export,同时定义时候需要指定是针对哪个控件。如图指定了控件Select,然后就可以指定Select的专有属性了。

●Extend特点

1.方法不支持export。
和Styles一样,无法真正做到为所有页面抽离出都可用的属性方法。
2.方法只能定义为当前页面内的全局方法。
一定程度上全局方法存在引用GlobalThis,具体副作用未知。
3.方法需要指定控件,其他控件无法使用,只能对专有控件做到了抽离
4.方法可以传入参。相比Styles, 可以在其他属性不变的情况下,只修改其中的部分属性。

AttributeModifier

对于上述两个装饰器都存在一个相同的限制,就是无法做到全局所有文件都可以公用。
    
    AttributeModifier的出现可以变相的解决这个问题。AttributeModifier本意是用于自定义控件中设置属性用的。但是我们在这里也可以通过这个机制,来实现全局所有文件中控件均可通用的属性。

●代码说明
在这里插入图片描述

该Modifier只能针对专用控件,比如我要抽离一个通用的TextInput,那么我可以如上图所定义。
   
    需要实现一个接口 AttributeModifier,接口泛型定义和我们想要给哪个控件使用有关,比如我们想给TextInput使用,那么泛型就是 TextInputAttribute,如果给Column使用,那么泛型就是ColumnAttribute,以此类推。
   
    在该接口的实现方法中,定义控件的属性。

●布局中使用
在这里插入图片描述

●自定义属性

我们还可以自定义部分属性,只需要修改TextInputAttribute,例如我们想自定义字体大小。可以定义变量。

在这里插入图片描述

●使用
在这里插入图片描述

●AttributeModifier特点

1.可以全局给所有页面中的控件使用
2.可以自定义任何控件中的属性,包括特有属性
3.可以通过修改代码做成链式调用
4.该方法需要new对象,比较笨重,需要书写较多代码

@Builder

上述说的都是针对单独的控件,如果我们想抽离一个通用的布局呢?或者我们的控件就是固定的可以拿来到处使用。
    比如我有一个Text,各种属性固定,只是文案不同,那么我使用上述几种都比较麻烦,需要书写较多代码。那么这个时候就可以使用builder了。

●代码
在这里插入图片描述

我们可以在任意需要展示该Text的地方使用,直接调用该方法,对应位置就可以显示出内容了。原理相当于是将方法内的控件代码放到了对应的位置上。

●使用

在这里插入图片描述

● @Builder特点

1.定义好方法后,需要拿Builder装饰器修饰,可以在任何一个页面内调用方法使用。
2.可以通过方法传递入参
3.无法通过方法拿到控件对象,只能在方法里操作控件属性
4.除了单一控件,还可以定义布局,布局中存在多个控件的情况
5.轻量级
6.方法即拿即用,代码量少

struct

有时候,我们可能页面中存在大量如下UI:
在这里插入图片描述

对于这种UI,我们完全可以抽离出为一个控件。然后我们页面需要展示的地方,直接调用该控件,设置标题,按钮文案等就可以简化了。
    我们可能想到使用builder来定义,但是builder只能写纯UI代码,这里还涉及到用户输入的内容,如何在点击按钮时候传过去。所以builder就无法使用了,这个时候就可以用struct封装了。

●代码

@Component
export struct InputNumberItemWithButton {
  label: string = "标题"
  buttonClick: (v: number) => void = () => {
  }
  buttonLabel: string = "设置"
  inputPlaceholder: string = "我是提示语"
  inputId: string = this.label
  parentWidth: string = '100%'
  private value: number = 0

  build() {
    RelativeContainer() {
      Text(this.label)
        .attributeModifier(Modifier.textLabel())
        .id('label1')
        .alignRules({
          left: { anchor: '__container__', align: HorizontalAlign.Start },
          top: { anchor: '__container__', align: VerticalAlign.Top },
          bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
        })
        .margin({ left: 2 })

      TextInput({ placeholder: this.inputPlaceholder })
        .onChange((value: string) => {
          this.value = Number.parseInt(value) ?? 0
        })
        .type(InputType.Number)
        .id(this.inputId)
        .height(30)
        .placeholderFont({ size: 10 })
        .fontSize(CommonStyle.INPUT_TEXT_SIZE)
        .borderRadius(4)
        .alignRules({
          right: { anchor: 'button1', align: HorizontalAlign.Start },
          left: { anchor: 'label1', align: HorizontalAlign.End },
          top: { anchor: '__container__', align: VerticalAlign.Top },
          bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
        })
        .margin({ left: 6, right: 6 })

      Button(this.buttonLabel)
        .attributeModifier(SuBaoSmallButtonModifier.create())
        .onClick(() => {
          this.buttonClick(this.value)
        })
        .id('button1')
        .alignRules({
          right: { anchor: '__container__', align: HorizontalAlign.End },
          top: { anchor: '__container__', align: VerticalAlign.Top },
          bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
        })
        .margin({ right: 2 })
    }
    .width(this.parentWidth)
    .height(40)
    .padding({
      left: 5,
      right: 5,
      top: 2,
      bottom: 2
    })
    .borderRadius(4)
  }
}

该struct中通过维护一个变量value 来保存用户输入的数字,然后在用户点击按钮时候传给点击事件方法,交给调用者调用。

●使用
在这里插入图片描述

点击设置按钮,点击事件触发,a直接赋值。

●struct特点

1.可以封装复杂组件,自定义组件
2.可以维护变量存储用户输入输出
3.可以所有页面全局使用
4.可以自定义属性
6.无法链式设置属性

对比各个使用场景

实际编程中,一般都是混合相互配合使用,没必要单独硬使用哪一个。

1.style可以用来定义一些通用属性,比如背景色,边角据等
2.Extend对于页面中一些特殊的控件,用的地方较多时候,可以抽离方法
3.AttributeModifier如果Extend无法满足,那么选择这个
4.Builder对于布局控件的属性变化不大,但是用的地方多时候使用,比如定义一个分割线。
5.struct涉及到用户输入输出时候,相关控件可以抽离封装,避免页面内上方定义太多变量,不好维护。

写在最后

有很多小伙伴不知道该从哪里开始学习鸿蒙开发技术?也不知道鸿蒙开发的知识点重点掌握的又有哪些?自学时频繁踩坑,导致浪费大量时间。结果还是一知半解。所以有一份实用的鸿蒙(HarmonyOS NEXT)全栈开发资料用来跟着学习是非常有必要的。

获取完整版高清学习资料,请点击→鸿蒙全栈开发学习资料(安全链接,请放心点击)

这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了

最新鸿蒙全栈开发学习线路在这里插入图片描述

鸿蒙HarmonyOS开发教学视频

在这里插入图片描述

大厂面试真题

在这里插入图片描述

在这里插入图片描述

鸿蒙OpenHarmony源码剖析

在这里插入图片描述

这份资料能帮住各位小伙伴理清自己的学习思路,更加快捷有效的掌握鸿蒙开发的各种知识。有需要的小伙伴自行领取,,先到先得~无套路领取!!

获取这份完整版高清学习资料,请点击→鸿蒙全栈开发学习资料(安全链接,请放心点击)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值