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

HarmonyOS NEXT 声明式UI语法学习笔记-创建自定义组件

基础语法概述

ArkTS的基本组成

装饰器:用于装饰类、结构、方法以及变量,并赋予其特殊含义。如上图都是装饰器,@Component表示自定义组件,@Entry表示表示自定义组件的入口组件,@State表示组件中的状态变量,当状态变量发生变化就会触发UI刷新。

自定义组件:可以复用的UI单元,可组合其他组件,如上述被@Component装饰的struct Index

系统组件:ArkUI框架中默认内置的基础和容器组件,可直接被调用,比如Button、Text、Row等

事件方法:组件可以通过链式调用设置多个事件的响应逻辑,例如Button后面加Onclick() 

声明式UI描述

Text

Text('小说简说简介小说简介小说简介小说简介小说简介小说简介小说简介小说简介小说简介小说简介小说简介小说简介').width('100%').lineHeight(25)//文本溢出省略号.textOverflow({overflow:TextOverflow.Ellipsis})//文本溢出必须配合maxLines才有效果.maxLines(3)

Image

// 加载网络图片Image('https://cn-assets.gitee.com/assets/Codeblitz-8824e38875a106e16e29ff57ec977b08.png').height(50)// 加载本地图片Image($r('app.media.app_icon')).height(50)

配置事件

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

 使用组件的成员函数配置组件的事件方法,需要bind this。

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

注意:在 ArkTS 中,不推荐使用成员函数配合 bind(this) 去配置组件的事件方法

1.性能开销:每次渲染都会重新绑定:当使用bind(this)时,每次组件重新渲染,都会创建一个新的函数实例。这是因为bind方法会返回一个新的函数,该函数内部绑定了特定的this值。如果组件频繁重新渲染,会不断创建新的函数实例,增加内存开销,影响性能。

2.代码可读性和维护性:使用 bind(this) 会使代码变得复杂,尤其是在处理多个事件或嵌套组件时,会增加代码的理解难度。开发者需要时刻关注 this 的指向,容易出现混淆

使用声明的箭头函数,可以直接调用,不需要bind this

Button('add counter'+this.counter).onClick(this.fn)
fn = () => {this.counter += 1}

创建自定义组件

在 ArkUI中,UI显示的内容均为组件,由框架直接提供的组件称为系统组件,由开发者定义的称为自定义组件。在进行UI界面开发时,通常不是把简单的系统组件进行组合使用,可是要考虑代码的复用性、业务逻辑和UI分离,后续版本演进等因素。因此,将UI和部分业务逻辑封装成自定义组件是不可或缺的能力。

自定义组件的基本用法

@Component
struct HelloComponent {@State message: string = 'Hello, World!';  build() {// HelloComponent自定义组件组合系统组件Row和TextRow() {Text(this.message).onClick(() => {// 状态变量message的改变驱动UI刷新,UI从'Hello, World!'刷新为'Hello, ArkUI!'this.message = 'Hello, ArkUI!';})}}
}

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

HelloComponent可以在其他自定义组件中的build()函数中多次创建,实现自定义组件的重用。

@Entry
@Component
struct ParentComponent {  build() {Column() {Text('ArkUI message')HelloComponent({ message: 'Hello World!' });  Divider()HelloComponent({ message: '你好,世界!' });}}
}

自定义组件的基本结构

struct

自定义组件基于struct实现,struct + 自定义组件名 + {...}的组合构成自定义组件,不能有继承关系。对于struct的实例化,可以省略new。但是要注意,自定义组件名、类名、函数名不能和系统组件名相同。

@Component

@Component装饰器只能装饰在struct关键字声明的数据结构。struct被@Component装饰后才能具备组件化能力,需要实现build方法描述。UI一个struct只能被一个@Component装饰。

在 ArkTS 里,@Component 是用于声明一个组件的装饰器,它可以接受一个可选的布尔类型参数,这个参数是 isStateless,其主要用途在于明确该组件是有状态组件还是无状态组件

参数含义 isStateless 为布尔类型,具体含义如下:

  • true:当传入 true 时,表明该组件是无状态组件。无状态组件不包含自身的状态(如 @State、@Link 等装饰的变量),其 UI 完全由传入的属性决定,只要输入的属性不变,组件的 UI 就不会发生变化。无状态组件相对简单,渲染性能通常更高。
  • false:当传入 false 或者不传入该参数时,默认该组件是有状态组件。有状态组件可以包含自身的状态,这些状态会随着用户操作或其他事件发生改变,从而触发组件的重新渲染以更新 UI。

 代码示例

无状态代码示例:

// 定义一个无状态组件,将 isStateless 参数设置为 true
@Component({ isStateless: true })
struct StatelessComponent {// 定义一个属性,用于接收外部传入的值msg: string;build() {// 在组件的构建函数中,使用传入的属性来构建 UIText(this.msg).fontSize(20)}
}// 在另一个组件中使用无状态组件
@Entry
@Component
struct ParentComponent {build() {Column() {// 创建 StatelessComponent 实例,并传入属性值StatelessComponent({ msg: 'This is a stateless component.' })}.width('100%')}
}

在上述代码中,StatelessComponent 是一个无状态组件,它没有自己的状态,UI 完全由外部传入的 msg 属性决定。

有状态代码示例:

// 定义一个有状态组件,不传入 isStateless 参数,默认是有状态的
@Component
struct StatefulComponent {// 使用 @State 装饰器定义一个有状态的变量@State count: number = 0;build() {Column({ space: 20 }) {// 显示当前的计数Text(`Count: ${this.count}`).fontSize(20)// 创建一个按钮,点击时增加计数Button('Increment').onClick(() => {this.count++;})}.width('100%')}
}@Entry
@Component
struct MainComponent {build() {Column() {// 使用有状态组件StatefulComponent()}.width('100%')}
}

在这个例子中,StatefulComponent 是一个有状态组件,它包含一个 @State 装饰的 count 变量,当用户点击按钮时,count 的值会改变,从而触发组件的重新渲染。

通过传入 isStateless 参数,开发者可以根据组件的特性和需求,灵活选择使用有状态组件或无状态组件,以达到更好的性能和可维护性。

build()函数

 build()函数用于定义自定义组件的声明式UI描述,自定义组件必须定义build()函数

@Component
struct MyComponent {build() {}
}

@Entry

@Entry装饰的自定义组件将作为UI页面的入口。在单个UI页面中,最多可以使用@Entry装饰一个自定义组件。@Entry可以接受一个可选的
LocalStorage的参数。

LocalStorage 是一种在浏览器(类似概念在 HarmonyOS 等系统中也有应用)中用于存储数据的机制,它允许开发者在客户端本地存储键值对数据,并且这些数据在浏览器会话期间(甚至在浏览器关闭后再次打开时)都会保留,除非手动清除。在 ArkTS 的上下文中,LocalStorage 提供了一种持久化存储应用程序状态或数据的方式,以便在页面重新加载或应用重启后仍能恢复之前的状态。

@Entry
@Component
struct MyComponent {
}

 @Reusable

@Resuable装饰器的主要作用是让组件可以被复用,避免重复创建相同的组件实例,从而提升性能。

应用场景

1. 列表渲染场景

在开发列表类界面时,通常会有大量相同类型的列表项。使用 @Reusable 装饰器可以复用这些列表项组件,减少内存开销和渲染时间。

// 定义可复用的列表项组件
@Reusable('ListItem')
@Component
struct ListItem {@Link private item: string;build() {Row({ space: 5 }) {Text(this.item).fontSize(18).margin({ left: 10 })}.width('100%').padding(10).border({ width: 1, color: Color.Grey })}
}// 使用可复用组件的列表页面
@Component
struct ListPage {private listData: string[] = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5'];build() {Column({ space: 10 }) {ForEach(this.listData, (item: string) => {// 复用 ListItem 组件ListItem({ item: $item })}, (item: string) => item)}.width('100%')}
}

2. 弹窗组件复用

在应用中,可能会多次使用相同样式和功能的弹窗组件,如确认弹窗、提示弹窗等。使用 @Reusable 装饰器可以提高弹窗组件的复用性。

// 定义可复用的确认弹窗组件
@Reusable('ConfirmDialog')
@Component
struct ConfirmDialog {@Link private visible: boolean;private message: string;private onConfirm: () => void;build() {if (this.visible) {Dialog({onCancel: () => {this.visible = false;}}) {Column({ space: 20 }) {Text(this.message).fontSize(18)Button('确认').onClick(() => {this.visible = false;this.onConfirm();})}.width('100%').padding(20)}}}
}// 使用确认弹窗组件的页面
@Component
struct MainPage {@State private showConfirmDialog: boolean = false;private confirmAction() {console.log('确认操作执行');}build() {Column({ space: 20 }) {Button('显示确认弹窗').onClick(() => {this.showConfirmDialog = true;})// 复用确认弹窗组件ConfirmDialog({visible: $showConfirmDialog,message: '确认要执行此操作吗?',onConfirm: this.confirmAction})}.width('100%').padding(20)}
}

成员函数/变量

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

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

自定义组件可以包含成员变量,成员变量具有以下约束:

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

  • 自定义组件的成员变量本地初始化有些是可选的,有些是必选的。具体是否需要本地初始化,是否需要从父组件通过参数传递初始化子组件的成员变量

自定义组件通用样式

自定义组件通过“.”链式调用的形式设置通用样式。

@Component
struct ChildComponent {build() {Button(`Hello World`)}
}@Entry
@Component
struct MyComponent {build() {Row() {ChildComponent().width(200).height(300).backgroundColor(Color.Red)}}
}

HarmonyOS官网学习指南

相关文章:

HarmonyOS NEXT 声明式UI语法学习笔记-创建自定义组件

基础语法概述 ArkTS的基本组成 装饰器:用于装饰类、结构、方法以及变量,并赋予其特殊含义。如上图都是装饰器,Component表示自定义组件,Entry表示表示自定义组件的入口组件,State表示组件中的状态变量,当状…...

补充二分LIS

B3637 最长上升子序列 题目描述 这是一个简单的动规板子题。 给出一个由 n ( n ≤ 5000 ) n(n\le 5000) n(n≤5000) 个不超过 1 0 6 10^6 106 的正整数组成的序列。请输出这个序列的最长上升子序列的长度。 最长上升子序列是指,从原序列中按顺序取出一些数字排…...

用户模块——握手验证

1. 引言 在现代 Web 应用中,WebSocket 以其全双工通信、低延迟、减少 HTTP 开销等优势,被广泛应用于即时通讯、在线游戏、实时数据推送等场景。然而,在涉及用户认证时,WebSocket 存在一个常见问题——每次刷新页面都会重新建立 We…...

97.HarmonyOS NEXT跑马灯组件教程:基础概念与架构设计

温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT跑马灯组件教程:基础概念与架构设计 1. 跑马灯组件概述 跑马灯(Marquee)是一种常见的UI组件&a…...

81.HarmonyOS NEXT 状态管理与响应式编程:@Observed深度解析

温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! HarmonyOS NEXT 状态管理与响应式编程:Observed深度解析 文章目录 HarmonyOS NEXT 状态管理与响应式编程:Observed深度解析…...

【Agent】OpenManus-Agent架构详细分析

各组件详细设计见: BaseAgent:BaseAgentReActAgent:ReActAgentToolCallAgent:ToolCallAgent具体Agent实现:具体AgentMemory数据结构:Memory 1. 智能体层次结构 OpenManus 采用了一个多层次的智能体继承结…...

股指期货有卖不出去的时候吗?

在股指期货的交易世界里,很多人都有这样的疑问:股指期货会不会有卖不出去的时候呢?答案是会的,下面咱们就来详细唠唠为啥会出现这种情况。 市场极端行情下难以卖出 1.跌停限制:股指期货和股票一样,也有涨…...

前端Html5 Canvas面试题及参考答案

目录 Canvas 元素的默认尺寸是多少?如何正确设置其宽高以避免图像拉伸? 如何获取 Canvas 的 2D 上下文对象?3D 上下文支持哪些技术? canvas.width 与 canvas.style.width 的区别是什么? Canvas 支持的图像格式有哪些?如何将 Canvas 转换为 Base64 图片? Canvas 中如…...

【ES6】03-Set + Map

本文介绍两种集合 set map 的操作和方法。 目录 1. Set 1.1 set基本使用 1.2 add 1.3 delete 1.4 has 1.5 size 1.6 set转换为数组 1.7 拓展运算符 1.8 for...of 1.9 forEach 1.10 set给数组去重 2. Map 2.1 创建map集合 2.2 set添加元素 2.3 delete删除元素 …...

Java缓存String(字符串常量池)、Integer (-128 到 127 )

对问题的解释 1. “字符串常量池存储的是string对象的直接引用,而不是直接存放的对象,是一张string table” 的含义 这句话可以从以下几个方面理解: (1) 字符串常量池的存储内容 直接引用:字符串常量池中存储的是指向实际 Stri…...

消息队列的特性与使用场景:Kafka、ActiveMQ、RabbitMQ与RocketMQ的深度剖析

在分布式系统和微服务架构中,消息队列是实现服务间通信和解耦的核心组件。Kafka、ActiveMQ、RabbitMQ和RocketMQ是当前最受欢迎的消息队列解决方案,它们各自具有独特的特性和适用场景。本文将从特性和使用场景两个维度进行对比分析,帮助读者更…...

开发、科研、日常办公工具汇总(自用,持续更新)

主要记录汇总一下自己平常会用到的网站工具,方便查阅。 update:2025/2/11(开发网站补一下) update:2025/2/21(补充一些AI工具,刚好在做AI视频相关工作) update:2025/3/7&…...

解决VueI18n使用浏览器插件翻译后,切换国际化失效的问题

问题复现 在使用Vue-i18n对页面进行国际化的时候,使用浏览器翻译插件(如腾讯翻译)后,切换国际化语言,随后当我们关闭浏览器翻译插件后,再次切换国际化语言,原来被翻译的文字无法正确切换 出现…...

HTML5 drag API实现列表拖拽排序

拖拽API(Drag and Drop API)是HTML5提供的一组功能,使得在网页上实现拖放操作变得更加简单和强大。这个API允许开发者为网页元素添加拖拽功能,用户可以通过鼠标将元素拖动并放置到指定的目标区域。 事件类型 dragstart&#xff1…...

改变一生的思维模型【11】升维

升维思维模型:突破认知局限的破局法则 一、定义与核心逻辑 升维思维是通过增加分析维度,将问题投射到更高认知层次寻找解决方案的思考方式。其本质是跳出原有竞争维度,在更广阔的空间重构游戏规则。核心逻辑在于:当低维战场陷入…...

【动手学深度学习】#2线性神经网络

主要参考学习资料: 《动手学深度学习》阿斯顿张 等 著 【动手学深度学习 PyTorch版】哔哩哔哩跟李牧学AI 目录 2.1 线性回归2.1.1 线性回归的基本元素线性模型损失函数解析解随机梯度下降 2.1.3 最大似然估计 2.2 线性回归从零开始实现2.2.1 生成数据集2.2.2 读取数…...

计算机网络——NAT

一、什么是NAT? NAT(Network Address Translation,网络地址转换) 是一种将 私有IP地址 与 公有IP地址 相互映射的技术,主要用于解决IPv4地址不足的问题。它像一名“翻译官”,在数据包经过路由器或防火墙时…...

Stable Deffusion--常见模型插件详解

1.Checkpoint大模型 Checkpoint 是生成图像的基础模型,决定了整体画风如动漫、写实、机甲等。它是必选项,所有图像生成必须基于一个主模型。文件体积较大通常 1.5GB 以上,格式为 .ckpt 或 .safetensors。 存放位置为:\models\Sta…...

防重复提交详解:从前端Vue到后端Java的全面解决方案

防重复提交详解:从前端Vue到后端Java的全面解决方案 一、重复提交问题概述 在Web应用开发中,表单重复提交是一个常见问题,可能导致: 数据库中出现重复记录重复执行业务逻辑(如多次扣款)系统资源浪费用户…...

同一子网通信

添加交换机后的通信流程 1. 同一子网内(使用交换机) 判断是否在同一子网: 主机A通过子网掩码判断主机B的IP地址是否属于同一子网。若在同一子网,主机A需要通过ARP获取主机B的MAC地址。 ARP请求(广播)&…...

快速迭代:利用 nodemon 和其他工具实现 Express.js 热更新

在开发 Express.js 应用时,热更新(Hot Reloading)可以显著提升开发效率,因为它允许你在修改代码后立即看到效果,而无需手动重启服务器。以下是几种实现热更新的方法和工具,帮助你在开发过程中更高效地工作。…...

BUG日志:Maven项目启动报错(文件名或者文件扩展名过长)

Bug日志编号:[Maven-001] 标题:Windows系统下Maven项目因路径过长导致命令行执行失败 1. 问题描述 现象:执行mvn clean install时报错: The input line is too long 或 The filename or extension is too long触发条件&#xf…...

IntelliJ IDEA 快捷键系列:重命名快捷键详解

目录 引言一、默认重命名快捷键1. Windows 系统‌2. Mac 系统‌ 二、操作步骤与技巧1. 精准选择重命名范围‌2. 智能过滤无关内容‌ 三、总结 引言 在代码重构中,‌重命名变量、类、方法‌ 是最常用的操作之一。正确使用快捷键可以极大提升开发效率。本文针对 ‌Ma…...

零基础掌握分布式ID生成:从理论到实战的完整指南 [特殊字符]

一、为什么需要分布式ID? 🤔 在单机系统中,使用数据库自增ID就能满足需求。但在分布式系统中,多个服务节点同时生成ID时会出现以下问题: ID冲突:不同节点生成相同ID 扩展困难:数据库自增ID无法…...

使用python反射,实现pytest读取yaml并发送请求

pytest yaml yaml - feature: 用户模块story: 登录title: 添加用户request:method: POSTurl: /system/user/listheaders: nullparams: nullvalidate: nullread_yaml_all def read_yaml_all(path):with open(path, r, encodingutf-8) as f:value yaml.safe_load(f)return v…...

点灯、点各式各样的灯

鱼离水则身枯,心离书则神索。 前言闪灯呼吸灯流水灯二进制数显示灯蜂鸣器节拍流水音乐会总结 前言 上回书咱们简单了解了一点有关特殊功能寄存器sfr、通用输入输出GPIO、位操作运算符sbit和一个不靠单片机上的晶振(拿来定时的)的依托于单片机CPU空操作的ms级延时函…...

Matlab 汽车悬架系统动力学建模与仿真

1、内容简介 略 Matlab 170-汽车悬架系统动力学建模与仿真 可以交流、咨询、答疑 2、内容说明 略 本文对题目给定的1/2汽车四自由度模型,建立状态空间模型进行系统分析,并通过MATLAB仿真对系统进行稳定性、可控可观测性分析,对得的结果进行…...

专访数势科技谭李:智能分析 Agent 打通数据平权的最后一公里

作者|斗斗 编辑|皮爷 出品|产业家 伦敦塔桥下的泰晤士河底,埋藏着工业革命的隐秘图腾——布鲁内尔设计的隧道盾构机。在19世纪城市地下轨道建设的过程中,这个直径11米的钢铁巨兽没有选择拓宽河道,而是开创了地下通行的新维度。 “我们不…...

了解浏览器

本文来自腾讯元宝 Chrome浏览器(Google Chrome)是由Google开发的一款免费网页浏览器,自2008年发布以来凭借其高效、安全、简洁的特点成为全球市场份额最高的浏览器。以下是其核心信息及最新动态的综合分析: 一、核心优势与技术特点…...

2、操作系统之软件基础

一、硬件支持系统 ,系统管理硬件 操作系统核心功能可以分为: 守护者:对硬件和软件资源的管理协调者:通过机制,将各种各样的硬件资源适配给软件使用。 所以为了更好的管理硬件,操作系统引进了软件。其中3大…...