当前位置: 首页 > news >正文

OpenHarmony 入门——ArkUI自定义组件的基础语法(一)

文章大纲

  • 引言
  • 一、自定义组件的基本语法
    • 1、@Component 装饰器 和 @Entry 装饰器
    • 2、build函数
    • 3、@Reuseable
    • 4、定义成员函数/变量
  • 二、自定义组件的使用

引言

在OpenHarmony 系统里ArkUI子系统显示的内容均为组件,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。在进行 UI 界面开发时,通常不是简单的将系统组件进行组合使用,而是需要考虑代码可复用性、业务逻辑与UI分离,后续版本演进等因素。本文基本就是把官网文档重新整理了下。

一、自定义组件的基本语法

在OpenHarmony定义一个自定义组件语法很简单,通常来说只需要三步:

  • 定义一个被@Component 装饰器修饰的struct类型的自定义组件名
  • 在这个自定义组件的代码块内实现build函数
@Component
struct MyComponent {build() {}
}

1、@Component 装饰器 和 @Entry 装饰器

@Component 装饰器像其他一些装饰器一样是华为的ArkTS语言(基于原生TypeScript的扩展)开发的机制,编译时会自动生成一些“胶水代码”完成一些相应的任务,比如说@State背后的原理就类似于观察者模式的应用,@Component装饰器仅能装饰struct关键字声明的数据结构。struct被@Component装饰后且实现了build方法描述UI结构后才具备组件化的能力,一个struct只能被一个@Component装饰。@Component可以接受一个可选的bool类型参数。

//是否开启组件冻结。
@Entry
@Component({ freezeWhenInactive: true })
struct MyComponent {
}

并不是每一个组件都必须使用@Entry 装饰器,只有把这个自定义组件将作为UI页面的入口时才需要使用@Entry修饰。在单个UI页面中最多可以使用@Entry装饰一个自定义组件。@Entry可选参数:
在这里插入图片描述

从API version 10开始,@Entry可以接受一个可选的LocalStorage的参数或者一个可选的EntryOptions参数。

class PropB {code: number;constructor(code: number) {this.code = code;}
}
// 创建新实例并使用给定对象初始化
let para: Record<string, number> = { 'PropA': 47 };
let storage: LocalStorage = new LocalStorage(para);
storage.setOrCreate('PropB', new PropB(50));@Component
struct Child {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageLink('PropA') childLinkNumber: number = 1;// @LocalStorageLink变量装饰器与LocalStorage中的'PropB'属性建立双向绑定@LocalStorageLink('PropB') childLinkObject: PropB = new PropB(0);build() {Column() {Button(`Child from LocalStorage ${this.childLinkNumber}`) // 更改将同步至LocalStorage中的'PropA'以及Parent.parentLinkNumber.onClick(() => {this.childLinkNumber += 1;})Button(`Child from LocalStorage ${this.childLinkObject.code}`) // 更改将同步至LocalStorage中的'PropB'以及Parent.parentLinkObject.code.onClick(() => {this.childLinkObject.code += 1;})}}
}
// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct CompA {// @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定@LocalStorageLink('PropA') parentLinkNumber: number = 1;// @LocalStorageLink变量装饰器与LocalStorage中的'PropB'属性建立双向绑定@LocalStorageLink('PropB') parentLinkObject: PropB = new PropB(0);build() {Column({ space: 15 }) {Button(`Parent from LocalStorage ${this.parentLinkNumber}`) // initial value from LocalStorage will be 47, because 'PropA' initialized already.onClick(() => {this.parentLinkNumber += 1;})Button(`Parent from LocalStorage ${this.parentLinkObject.code}`) // initial value from LocalStorage will be 50, because 'PropB' initialized already.onClick(() => {this.parentLinkObject.code += 1;})// @Component子组件自动获得对CompA LocalStorage实例的访问权限。Child()}}
}

2、build函数

build()函数用于定义自定义组件的声明式UI描述,自定义组件必须定义build()函数。同时build函数里有一些约束规则:

  • @Entry装饰的自定义组件,其build()函数下的根节点唯一且必要,且必须为容器组件,其中ForEach禁止作为根节点。 @Component装饰的自定义组件,其build()函数下的根节点唯一且必要,可以为非容器组件,其中ForEach禁止作为根节点。

  • 不允许声明本地变量或者本地代码块(作用域),反例如下。

    build() {// 反例:不允许声明本地变量let a: number = 1;//反例{}
    }
    
  • 不允许在UI描述里直接使用console.info,但允许在函数里使用。

  • 不允许调用没有用@Builder装饰的方法,允许系统组件的参数是TS方法的返回值

@Component
struct ParentComponent {doSomeCalculations() {}calcTextValue(): string {return 'Hello World';}@Builder doSomeRender() {Text(`Hello World`)}build() {Column() {// 反例:不能调用没有用@Builder装饰的方法this.doSomeCalculations();// 正例:可以调用this.doSomeRender();// 正例:参数可以为调用TS方法的返回值Text(this.calcTextValue())}}
}
  • 不允许使用switch语法,如果需要使用条件判断,请使用if;也不允许使用三元表达式。
  • 不允许直接改变状态变量
@Component
struct CompA {@State col1: Color = Color.Yellow;@State col2: Color = Color.Green;@State count: number = 1;build() {Column() {// 应避免直接在Text组件内改变count的值Text(`${this.count++}`).width(50).height(50).fontColor(this.col1).onClick(() => {this.col2 = Color.Red;})}}
}

3、@Reuseable

@Reusable装饰的自定义组件具备可复用能力,结合懒加载等机制可以提高UI的性能。

@Reusable
@Component
struct MyComponent {
}

4、定义成员函数/变量

自定义组件除了必须要实现build()函数外,还可以实现其他成员函数,成员函数具有以下约束:

  • 自定义组件的成员函数为私有的,且不建议声明成静态函数。
  • 自定义组件可以包含成员变量,成员变量具有以下约束:

自定义组件的成员变量为私有的,且不建议声明成静态变量。

  • 自定义组件的成员变量本地初始化有些是可选的,有些是必选的。具体是否需要本地初始化,是否需要从- 父组件通过参数传递初始化子组件的成员变量,请参考状态管理。
@Entry
@Component
struct Parent {@State cnt: number = 0submit: () => void = () => {this.cnt++;}build() {Column() {Text(`${this.cnt}`)Son({ submitArrow: this.submit })}}
}@Component
struct Son {submitArrow?: () => voidbuild() {Row() {Button('add').width(80).onClick(() => {if (this.submitArrow) {this.submitArrow()}})}.justifyContent(FlexAlign.SpaceBetween).height(56)}
}

二、自定义组件的使用

组件可以在其他自定义组件中的build()函数中多次创建,实现自定义组件的重用,自定义组件的构造函数也可以支持有参数的实现。

@Entry
@Component
struct Parent {@State cnt: number = 0build() {Column() {Text(`${this.cnt}`)Son({ name:"crazymo" })}}
}@Component
struct Son {private name: string;Son(str: string){this.name= str;}build() {Row() {Button('add').width(80)})}}
}

如果在另外的文件中引用该自定义组件,需要使用export关键字导出,并在使用的页面import该自定义组件。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 开源项目的认识理解
  • 深度学习中的超参管理方法:argparse模块
  • Nodejs 第八十六章(部署pm2)
  • 如何在uniapp中使用websocket?
  • 如何选择一款适合自己的鼠标?
  • 在Mac上一键安装Mysql(解决所有安装问题)
  • 网络安全威胁也日益复杂,分布式拒绝服务(DDoS)攻击因其高频率和破坏力而成为一大挑战
  • Okhttp实现原理
  • linux kernel ptr dump
  • python 知识点累积
  • js逆向-webpack-python
  • YOLOv8损失函数改进-增加MPDIoU提升边界框回归精度【附代码】
  • 苹果入局,AI手机或将实现“真智能”?
  • Spring懒加载Bean机制
  • 昇思25天学习打卡营第19天 | 基于MindSpore通过GPT实现情感分类
  • Babel配置的不完全指南
  • ES6之路之模块详解
  • Fabric架构演变之路
  • passportjs 源码分析
  • PHP 的 SAPI 是个什么东西
  • php中curl和soap方式请求服务超时问题
  • puppeteer stop redirect 的正确姿势及 net::ERR_FAILED 的解决
  • python学习笔记 - ThreadLocal
  • Rancher-k8s加速安装文档
  • scala基础语法(二)
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • Three.js 再探 - 写一个跳一跳极简版游戏
  • Vue 重置组件到初始状态
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 微服务入门【系列视频课程】
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • Android开发者必备:推荐一款助力开发的开源APP
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • ​Kaggle X光肺炎检测比赛第二名方案解析 | CVPR 2020 Workshop
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #systemverilog# 之 event region 和 timeslot 仿真调度(十)高层次视角看仿真调度事件的发生
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • $ git push -u origin master 推送到远程库出错
  • ${ }的特别功能
  • (1)STL算法之遍历容器
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (51单片机)第五章-A/D和D/A工作原理-A/D
  • (javascript)再说document.body.scrollTop的使用问题
  • (TOJ2804)Even? Odd?
  • (阿里云万网)-域名注册购买实名流程
  • (超简单)使用vuepress搭建自己的博客并部署到github pages上
  • (初研) Sentence-embedding fine-tune notebook
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (七)Java对象在Hibernate持久化层的状态
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (十一)c52学习之旅-动态数码管
  • (原)Matlab的svmtrain和svmclassify
  • (终章)[图像识别]13.OpenCV案例 自定义训练集分类器物体检测