
HarmonyOS组件基础 原创
1.组件-什么是ArkTS
ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript(简称TS)生态基础上做了进一步扩展,继承了TS的所有特性,是TS的超集。
说明: 也就是前端开发过程中所有的js/ts语法大部分支持的,比如es6中的箭头函数-模板字符串-promise-async/await-数组对象方法。
注意: 根据Next版本的内部沟通,下一版本的ArkTs对类型最了更一步的限制。
https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/typescript-to-arkts-migration-V5
这里注意:ArtTS绝不是TS。
①TS在前端中虽然有类型约束,但是他会编译成js去运行。
②ArtTS编译后直接映射字节码-编译过程带类型。
扩展能力如下:
①基本语法
- 定义声明式UI、自定义组件、动态扩展UI元素;
- 提供ArkUI系统组件,提供组件事件、方法、属性;
- 共同构成 UI 开发主体。
②状态管理
- 组件状态、组件数据共享、应用数据共享、设备共享;
③渲染控制
- 条件渲染、循环渲染、数据懒加载;
声明式UI
总结:
①AktTS提供原有前端范畴内的一切TypeScript和JavaScript的类型及方法支持。
②不是所有都支持- 比如解构不支持(Next版本)。
③ArkTS采用声明式UI的方法来绘制页面,设置属性,绑定事件。
2.组件结构
接下来,我们来解析我们的UI的结构。
ArkTS通过装饰器 @Component 和 @Entry 装饰 struct 关键字声明的数据结构,构成一个自定义组件。
自定义组件中提供了一个 build 函数,开发者需在该函数内以链式调用的方式进行基本的 UI 描述,UI 描述的方法请参考 UI 描述规范。
(1)struct-自定义组件基于struct
实现
要想实现一段UI的描述,必须使用struct关键字来声明- 注意不能有继承关系-组件名不能系统组件名重名。
语法: struct 组件名 {}。
struct关键字声明的UI描述-必须被@Component或者@CustomDialog修饰。
(2)Component修饰符
Component装饰器只能修饰struct关键字声明的结构,被修饰后的struct具备组件的描述(渲染)能力。
(3)build函数
用于定义组件的UI描述,一个struct结构必须实现build函数。
build函数是组件(Component)必须提供以及实现的一个函数,build函数可以没有内容,如果有的话,必须有且只有一个容器组件(可以放置子组件的组件)- 只有entry里面有限制- component里面没有限制。
常见容器组件- Flex-Column-Row-List-Grid-Panel。
(4)entry修饰符
entry将自定义组件定义为UI页面的入口,也就是我们原来前端常说的一个页面,最多可以使用entry装饰一个自定义组件(在一个ets文件中)-如下面的代码就是不被允许的。
entry修饰的组件,最终会被注册,具体文件位置-main/resources/base/profile/main_pages.json。
①自动注册-新建组件时,采用新建Page的方式。
②手动注册-新建一个ets文件,自己在main_pages.json中手动添加路径。
注意:
如果手动删除了某一个带entry的组件,你需要手动去main_page中去删除该路径,否则编译会报错。
(5)组件复用
在很多情况下,由于业务的复杂度,经常会将一个大的业务拆成若干个组件,进行组装,这里我们非常灵活的复用组件,比如:
可以把上图抽象成三个组件- Header- Main- Footer。
运行效果,如图所示:
总结:
· 一个UI描述必须使用struct来声明,不能继承。
· struct必须被Component或者CustomDialog修饰。
· struct必须实现build方法,build方法可以没有元素,但是有的话有且只有一个可容纳子组件的容器组件(entry修饰的组件)。
· entry修饰符表示该组件是页面级组件,一个文件中只允许修饰一个struct组件。
· 采用分拆组件的形式可以有效解解耦我们的业务。
3.系统组件(ArkUI)
常用系统组件:
Button Text Column Row Flex Stack Scroll List TextInput Image 更多组件。
组件使用:
· Text 文本组件-(Span子组件)
· Column 列组件,纵向排列,Flex布局主轴是Y (任意子组件)
· Row 行组件,横向向排列,Flex布局主轴是X (任意子组件)
· Flex 以弹性方式布局子组件的容器组件。(
存在二次布局,官方推荐有性能要求,使用Column和Row代替) (任意子组件)
· Button 按钮组件 (单子组件)
· TextInput 输入框组件 (无子组件)
· Image (无子组件)
· Button (单个子组件)
· List (限制ListItem子组件)
· Scroll (限制单个子组件)
组件使用语法:
· 使用组件采用组件名() 的语法
· 有构造参数采用组件名(参数)的语法
· 组件里放置子组件采用组件名() {子组件的语法 } 的链式语法
· 组件设置属性采用组件名().width().height() 的语法
· 组件又有属性又有子组件采用组件名(){ ...子组件 }.width().height() 的语法
接下来,我们来实现一个布局的小例子测试一下我们的能力。
(1)横向布局
实现效果:
代码实现:
(2)纵向布局
实现效果:
代码实现:
(3)Flex横纵向
实现效果:
代码实现:
在arkUI中,我们的内容如果超过了屏幕显示,则不会显示滚动条,需要使用Scroll来包裹。
需要注意的是:
该组件滚动的前提是主轴方向大小小于内容大小。子组件不要设置高度,否则不能滚动。
4.组件事件
监听原生组件的事件和设置属性的方式是一样的都是链式调用,值得注意的是,我们注册事件都要使用箭头函数的写法,HarmonyOS 5.0版本会有对于匿名函数function的限制。
尝试给一个TextInput和一个按钮注册一个值改变事件和点击事件。
(1)事件定义
实现效果:
点击登录后的效果:
代码实现:
请注意:在注册事件中的逻辑务必使用箭头函数() => {},极不推荐function() {}。
①因为function中this指向为undefind
②HarmonyOS 5.0不再支持funtion匿名函数声明
③箭头函数中的this指向当前struct实例,可以方便的调用方法和获取属性
当我们事件处理逻辑比较复杂,写在UI描述中无法抽提的时候,我们可以在struct结构体中定义。
(2)属性定义
当我们需要在组件中记录一些状态时,变量应该显示的在struct中声明,并注明类型,比如-登录账户和密码。
我们看代码示例时,会发现 public和private关键字,
如果不写或者写public 表示该属性可被外界即父组件赋值,
如果写private表示该属性只会被该组件的this获取。
下面实现一个简单的登录过程:
示例代码:
说明
promptAction和AlertDailog都可以弹出提示 promptAction需要引入包,AlertDialog不需要引入就可以直接使用。
再加一个小需求,当用户名和密码为空时,不让用户点按钮。
代码如下:
我们发现,好像没有变化!!!为什么? 因为我们定义的变量是非响应式数据,值的变化无法导致build函数重新执行, 这就需要引出State修饰符了。
响应式数据- 数据驱动视图更新。
5.组件状态
@State装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。当状态改变时,UI会发生对应的渲染改变。
如何使用 @State 定义一个状态变量?
(1)组件变量,不具备驱动UI更新能力。
加上该修饰符后,你惊奇的发现按钮随着数据的变化在变化,因为我们在值改变的时候赋值,造成了build的重新执行,isSubmitFn 函数会重新执行,来保证我们状态的变化。
需要注意的是,State修饰的类型包括:
Object、class、string、number、boolean、enum类型,以及这些类型的数组。类型必须被指定。不支持any,不支持简单类型和复杂类型的联合类型,不允许使用undefined和null。
接下来,我们完成一个数据修改的案例,来看下state的特性。
步骤1:先声明一个User类,interface是ArkTS主推的定义对象类型的形式。
完整代码如下:
点击修改数据按钮,设置新数据
运行效果:
点击修改数据,可以修改用户名
大家发现,如果state是一个对象,我们改第一层的数据没问题,但是第二层的数据不触发更新,怎么办?
我们依然可以改第一层的数据。如:
代码如下:
