CPU都被干冒烟了,拥抱HarmonyOS第二天,自定义组件(上)

简介: CPU都被干冒烟了,拥抱HarmonyOS第二天,自定义组件

在这两天的学习过程中,我发现了一个巨诡异的事情,那就是明明第一次在文档中找到的内容,结果第二次想要通过搜索找到他,打死都找不到,这种情况出现了三次。arkUI 的文档是真神奇!


那种诡异感甚至差点让我以为自己穿越了...


第二天没有什么实际的产出,但是学习进展非常明显,直接把自定义组件相关的知识 ~


学!完!了!


我把主要学习精力放在了区别 arkUI 和 React/vue 的差异、以及在封装一些比较有难度的基础组件的实现方式上。


比如我想要封装一个体验良好的表单组件,那么我的学习思路是


  • T、学习思路
  • 1、复杂UI布局应该怎么做 ✅
  • 2、基础的动画细节应该如何实现 ✅
  • 3、数据管理应该怎么做 ✅
  • 4、表单验证应该怎么做 ✅
  • 5、数据量复杂的时候有没有可能存在性能问题,还没有验证过,若在实践中遇到问题,针对性的优化即可


如果目的一样,当我攻克了和 React 的差异,在 HarmonyOS 上基于 arkUI 实现一套大厂可商用的基础组件就比较简单了。


这意味着什么呢?


意味着我已经可以开始撸大型实战项目啦!剩下还有很多不熟悉的组件和系统能力,只需要在用到的时候,阅读文档拿来使用,在后续的开发过程中慢慢熟练即可。所以呢,有想要组建 HarmonyOS 开发团队的老板们可以开始联系我了,我给你们当技术指导,哈哈。


我今天学习的主要内容包括:


系统组件生命周期
onAppear:组件挂载到组件树之后调用
onDisAppear:组件卸载时调用
页面组件生命周期
onPageShow:页面每次显示时触发
onPageHide:页面每次隐藏时触发
onBackPress:用户点击返回按钮时触发
自定义组件生命周期
aboutToAppear:组件即将出现时触发,在 build 之前
aboutToDisappear:组件即将销毁时触发
组件级别状态管理
@State
@Prop
@Link
@Provide/@Consume
@Observed
@ObjectLink
应用级别状态管理
@StorageProp
@StorageLink
@LocalStorageProp
@LocalStorageLink
其他状态管理
@Watch
$$ 运算符
T. 状态交互
1. 传参与接受参数
2. 子组件控制父组件
3. 父组件控制子组件

练习了大量的交互 Demo,并成功封装了两个可商用的基础组件

Icon Lottie
字体图标组件 Lottie 动画组件

在 React 里,一个 state 一个 props 就完事了,万万没想到在 arkUI 里知识点这么多。在研究组件交互的过程中,我的 CPU 直接被干冒烟了,根据我的学习感受,这必定会成为一个比较难掌握的点,要吃透他不太容易


01组件分类


在 arkUI 里,组件主要分为三个大类


  • 系统组件 主要是指系统原生提供的一系列组件,例如 Text、Button、CheckBox 等
  • 页面组件 被装饰器 @Entry 装饰的组件为页面组件,他表示一个页面的入口,该组件为页面的根节点
  • 自定义组件 我们可以通过装饰器 @Component 定义新的组件


02组件基础语法


一个页面组件中最基础的写法如下

@Entry
@Component
struct MyComponent {
  build() {
    Text('hello world!')
  }
}

页面组件必须被 @Entry 装饰。build 方法中包含所有的页面元素。在上面这个例子中,Text 组件执行实际上是一个初始化的过程,但是由于关键字 struct 的作用,因此省略了 new.


系统提供的基础组件以 . 链式调用的方式设置当前组件的样式


例如,设置 Text 组件的字体大小

Text('test')
  .fontSize(12)

也可以同时配置多个属性

Image('test.jpg')
  .alt('error.jpg')    
  .width(100)    
  .height(100)

除了直接传递常量参数之外,还可以传递变量和表达式

Text('hello')
  .fontSize(this.size)
Image('test.jpg')
  .width(this.count % 2 === 0 ? 100 : 200)    
  .height(this.offset + 100)

arkUI 系统提供了一些全局的枚举类型,可以作为参数传递

Text('hello')
  .fontSize(20)
  .fontColor(Color.Red)
  .fontWeight(FontWeight.Bold)

如果某个元素想要设置事件监听,同样以 . 链式调用的方式使用

Button('Click me')
  .onClick(() => {
    this.myText = 'ArkUI';
  })


this


习惯了箭头函数和函数式组件的 React 开发者就要注意了,在面向对象的语境下,需要随时确保 this 的引用发生变化,因此如下两种情况都需要使用 bind 绑定 this

Button('add counter')
  .onClick(function(){
    this.counter += 2;
  }.bind(this))

这是个坑啊,折磨了多少开发者,他又来了!

myClickHandler(): void {
  this.counter += 2;
}
...
Button('add counter')
  .onClick(this.myClickHandler.bind(this))


组件嵌套


组件嵌套的方式,就是在父组件后面添加 {},所有的容器组件都支持嵌套子组件

Column() {
  Text('Hello')
    .fontSize(100)
  Divider()
  Text(this.myText)
    .fontSize(100)
    .fontColor(Color.Red)
}


@Builder


有的时候我们希望把一段组件的逻辑单独抽离出来,可以使用 @Builder 装饰器来声明一个自定义构建函数

@Entry
@Component
struct MyComponent {
  @Builder helloHarmonyOS() {
    Text('Hello HarmonyOS')
  }
  build() {
    Row() {
      Text('hello world!')
      this.helloHarmonyOS()
    }
  }
}

但是这个 @Builder 装饰器在传参数的时候,有特别的规则,我们后面在学习状态管理的时候一起分享

我们可以在一个组件里定义多个 @Builder 声明的函数,也可以在全局定义

@Builder 
function MyGlobalBuilderFunction() {
}


@Styles


我们可以使用 @Styles 装饰器来解决样式复用的问题。

@Entry
@Component
struct MyComponent {
  @Builder helloHarmonyOS() {
    Text('Hello HarmonyOS')
      .fancy()
  }
  @Styles fancy() {
    .width('100%')
    .height(40)
    .backgroundColor(Color.Pink)
  }
  build() {
    Row() {
      Text('hello world!')
        .fancy()
      this.helloHarmonyOS()
    }
  }
}

需要注意的是,@Styles 目前仅支持通用属性和通用事件。


具体属性有哪些可以去官方文档查看,或者根据 DevEco 的代码提示来编写


@Styles 也不支持传入参数

// bad
@Styles 
- function globalFancy (value: number) {
-  .width(value)
}

@Styles 可以定义在组件内,也可以定义在全局,在全局定义时需要在方法名之前添加 function 关键字

// 全局
@Styles function functionName() { ... }
// 在组件内
@Component
struct FancyUse {
  @Styles fancy() {
    .height(100)
  }
}

组件内 @Styles 的优先级高于全局 @Styles。 框架优先找当前组件内的 @Styles,如果找不到,则会全局查找。

// 定义在全局的@Styles封装的样式
@Styles function globalFancy  () {
  .width(150)
  .height(100)
  .backgroundColor(Color.Pink)
}
@Entry
@Component
struct FancyUse {
  @State heightValue: number = 100
  // 定义在组件内的@Styles封装的样式
  @Styles fancy() {
    .width(200)
    .height(this.heightValue)
    .backgroundColor(Color.Yellow)
    .onClick(() => {
      this.heightValue = 200
    })
  }
  build() {
    Column({ space: 10 }) {
      // 使用全局的@Styles封装的样式
      Text('FancyA')
        .globalFancy ()
        .fontSize(30)
      // 使用组件内的@Styles封装的样式
      Text('FancyB')
        .fancy()
        .fontSize(30)
    }
  }
}

很坑爹的是,目前 @Styles 还不支持跨文件引入,这里的全局只能是同一个文件的全局 ~


@Extend


我们可以使用 @Extend 扩展原生组件样式

@Extend(UIComponentName) 
function functionName {
  ...
}
  • @Extend 仅支持全局定义
  • @Extend 支持封装指定原生组件的私有属性和方法,以及相同指定组件的 @Extend 方法
// 支持Text的私有属性fontColor
@Extend(Text) function fancy () {
  .fontColor(Color.Red)
}
// superFancyText可以调用预定义的fancy
@Extend(Text) 
function superFancyText(size:number) {
  .fontSize(size)
  .fancy()
}
  • @Extend 支持参数传入
// xxx.ets
@Extend(Text) 
function fancy (fontSize: number) {
  .fontColor(Color.Red)
  .fontSize(fontSize)
}
@Entry
@Component
struct FancyUse {
  build() {
    Row({ space: 10 }) {
      Text('Fancy')
        .fancy(16)
      Text('Fancy')
        .fancy(24)
    }
  }
}

传入的参数可以是 function

@Extend(Text) 
function makeMeClick(onClick: () => void) {
  .backgroundColor(Color.Blue)
  .onClick(onClick)
}
@Entry
@Component
struct FancyUse {
  @State label: string = 'Hello World';
  onClickHandler() {
    this.label = 'Hello ArkUI';
  }
  build() {
    Row({ space: 10 }) {
      Text(`${this.label}`)
        .makeMeClick(this.onClickHandler.bind(this))
    }
  }
}
相关文章
|
22天前
|
IDE 开发工具 Windows
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之RowSplit容器组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之RowSplit容器组件
66 0
|
22天前
|
IDE API 开发工具
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Counter容器组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Counter容器组件
50 1
|
22天前
|
IDE 开发工具 Windows
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之ColumnSplit容器组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之ColumnSplit容器组件
43 0
|
22天前
|
IDE API 开发工具
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Column容器组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Column容器组件
60 0
|
22天前
|
IDE API 开发工具
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Badge组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Badge组件
87 0
|
22天前
|
IDE API 开发工具
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之QRCode组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之QRCode组件
75 2
|
22天前
|
IDE 开发工具 数据安全/隐私保护
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之PatternLock组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之PatternLock组件
71 0
|
22天前
|
IDE API 开发工具
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Navigation组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Navigation组件
198 0
|
22天前
|
IDE 开发工具 Windows
 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之NavDestination组件
 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之NavDestination组件
69 3
|
22天前
|
IDE 开发工具 Windows
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之MenuItemGroup组件
鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之MenuItemGroup组件
33 1