鸿蒙开发
鸿蒙是华为自主研发的一款国产操作系统,学习鸿蒙编程,即可为多种鸿蒙终端开发应用,包含手机、平板、手表甚至是电视、汽车、嵌入式等。
配置环境 & IDE安装
鸿蒙开发需要使用的软件为DevEco Studio,它集成IntelliJ,为鸿蒙开发提供代码检查、自动补全、代码高亮以及提供常用工具,支持中文开发。
为书写方便,以下称 DevEco Studio 为IDE。
IDE的下载地址为https://developer.huawei.com/consumer/cn/deveco-studio/,进入后下载对应版本即可。
环境可在IDE下载完成之后在IDE中下载和配置。
下载完成后解压压缩包,得到一个exe安装包。
由于IDE基于IntelliJ构建,它的安装和使用界面和IDEA的旧UI很相似。
安装IDE
运行安装程序后,一路点击next即可。遇到协议则同意协议。
在安装完成后进入IDE的初始化界面,需要安装NodeJS、Ohpm和鸿蒙SDK。
第一次先安装NodeJS,由于华为鸿蒙对NodeJS等依赖的版本要求很苛刻,因此都选安装,不使用本地的。下一步还会安装ohpm,也是选择在线安装。
在 Summary中,继续即可。
进入安装界面后,先点击 Configure - Plugins,搜索Chinese,启用中文插件,然后重启IDE。
然后点击“新建项目”,创建我们的第一个鸿蒙项目。
点击next。
点击finish。
IDE界面组成
由于IDE和IDEA的界面很相似,这里只介绍大体的布局。
最左边树状的是文件树结构,中间为代码编辑区,点击右边的“预览器”,可以查看该页面的实时预览。
我们在刚学习鸿蒙开发时,只需要关注index.ets文件即可。在编写代码时,不要改变原有的代码,在其上面或下面写上自己的代码,然后在日志中查看即可。
ArkTS基础
方舟开发框架(简称ArkTS)为HarmonyOS应用的UI开发提供了完整的基础设施,包括简洁的UI语法、丰富的UI功能(组件、布局、动画以及交互事件),以及实时界面预览工具等,可以支持开发者进行可视化界面开发。
ArkTS是编写鸿蒙应用的一门编程语言,它和TypeScript语法很相似,比如定义变量和常量用const和let,打印用console.log等等。这里不详细介绍ArkTS的各种类型,因为都很简单,并且在TypeScript笔记中都记录了下来。
数据类型
ArkTS有三种基础数据类型:string、number、boolean。
let num: number = 123;
console.log("数字", num);
let bool: boolean = true;
console.log("布尔值", bool);
let str: string = "这是一个字符串";
console.log("字符串", str);
console.log()函数需要两个参数,第一个参数为信息,第二个参数为信息内容,这一点和JavaScript是不同的。
运行结果:
03-19 23:07:30.951 I A0c0d0/JSApp: app Log: 数字 123
03-19 23:07:30.951 I A0c0d0/JSApp: app Log: 布尔值 true
03-19 23:07:30.951 I A0c0d0/JSApp: app Log: 字符串 这是一个字符串
运行结果可在预览窗口更新以后,点击下方状态栏的日志即可查看。
###变量和常量
和JavaScript相似,ArkTS也具有变量和常量之分。变量使用let定义,常量使用const定义。
let variable = "这是一个变量";
variable = "变量的值可改变";
const constant = "这是一个常量";
constant = "常量的值不可以改变"; // 错误,常量的值不可改变
变量的命名规则如下。
- 只能使用数字、字母、下划线、$,不能以数字开头;
- 不能使用关键字;
- 严格区分大小写。
基本和其他编程语言一致。
数组
数组可以一次性存储多个数据。声明数组的语法为let 变量名: 类型名[] = [数据1, 数据2, ...]
let arr: number[] = [1, 2, 3, 4]
数组具有索引,从0开始,通过数组名[索引]
的方式获取数组元素的值。
let arr = ["黑龙江", "辽宁", "江苏", "北京"];
console.log("第三个元素", arr[2]); // 第三个元素 江苏
函数
函数是一段可以重复使用的代码块。我们之前使用的console.log就是系统封装的日志打印函数。
定义函数的语法为function 函数名(参数列表) {函数体}
,调用函数的语法为函数名(参数列表)
。
function add(a, b) {
console.log("两个数相加的结果为", a + b);
}
add(1, 2); //两个数相加的结果为 3
ArtTS支持定义箭头函数,定义箭头函数的语法是(参数列表) => {函数体}
。
let add = (a: number, b: number): number => {
return a + b
}
console.log("两个数相加:",add(1, 2));
接口
接口约定了一个对象必须要包含的属性。interface关键字用于定义接口,然后在接口里面声明属性和类型。
interface Person {
name: string, // 必须包含的属性
age: number,
gender?: string, // 可以包含的属性
sayHi: () => void // 必须包含的属性,此属性是一个成员方法
}
这时接口指定的名称就是我们的自定义类型。我们可以将对象指定为此类型,对象就必须包含该类型的属性。
let person: Person = {
name: "张三",
age: 18,
sayHi: () => console.log("提示信息", `你好,我是张三`)
}
console.log("名字:", person.name)
定义接口的方法时,也可以指定方法的参数和返回值。
interface Obj {
func: (a: number, b: string, c: boolean) => void
}
联合类型
联合类型可以允许一个变量有多种不同类型,以应变不同的需求。ArkTs使用管道符“|”隔开不同的变量类型。
let number: number | null = null;
let str: string | null = null;
此外,若想限制一个变量只能是一些值中的一种,可以将这些值当作类型使用,放在变量后面限制它们,并用管道符隔开。这一点和TypeScript中的字面值类型很像。
let gender: "男" | "女" | "保密" | null = null;
枚举类型
枚举类型约定变量只能在一组数据范围内选择值。枚举类型使用enum关键字定义,然后在里面声明枚举常量。每个枚举常量的值从0开始,以此类推,也可以在枚举类型内用赋值的形式给声明每一个枚举常量。
enum Month {
January,
February,
March,
// ...
}
enum Gender {
male = "男性",
female = "女性"
}
由于枚举内的内容为常量,即枚举常量,直接使用即可。
enum Month {
January,
February,
March,
// ...
}
enum Gender {
male = "男性",
female = "女性"
}
console.log("月份", Month.February)
console.log("性别", Gender.male)
function print(gender: Gender): void {
console.log("你选择的性别为", gender)
}
print(Gender.male)
界面开发 - 组件
学习界面开发,工具仍然是IDE,代码写在build函数中,然后在预览中查看界面。
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
build() { // 在这里面写代码
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
}
.width('100%')
}
.height('100%')
}
}
布局思路
编写界面应用时,应该先考虑排版,后填充内容。
ArkUI(方舟开发框架)是一套构建鸿蒙应用界面的框架。
构建页面的最小单位就是组件。
组件分为基础组件(如按钮、图片、文字)和容器组件(如行和列)。
容器组件的语法为容器组件(){ 组件内容 }
,基础组件的语法为基础组件(参数)
。
下面我们修改默认代码,对布局有一个基本的认识。
@Entry
@Component
struct Index {
build() {
Column() {
Text("学生列表")
Row() {
Text("张三")
Text("李四")
Text("王五")
}
}
}
}
需要注意,build()内部只能有一个根节点,不能再添加一个并列的容器组件。
组件属性方法
组件的属性方法可以更改组件的外观。语法:
组件() {
// 组件内容
}.属性方法(参数)
.属性方法(参数) //...
组件属性方法 | 描述 |
---|---|
.width(200) | 宽度 |
.height(200) | 高度 |
.backgroundColor(Color.pink) | 背景色 |
.fontSize(50) | 字体大小 |
.fontWeight(FontWeight.Bold) | 字体粗细 |
下面接着上方的代码为这些字体加一些样式。
@Entry
@Component
struct Index {
build() {
Column() {
Text("学生列表")
Row() {
Text("张三").backgroundColor(Color.Red)
.fontColor(Color.Orange)
.fontSize(50)
Text("李四").backgroundColor(Color.Blue)
.fontColor(Color.Pink)
.fontStyle(FontStyle.Italic)
Text("王五")
.backgroundColor(Color.Gray)
.fontWeight(FontWeight.Bolder)
}
}
}
}
字体颜色
语法:.fontColor(颜色值)
。其中,颜色值可以是Color的枚举值,或者为#开头的十六进制颜色图,和CSS一样。如:
Text("灰色").fontColor(Color.Gray)
Text("红色").fontColor("#FF0000")
文字溢出省略号、行高
- 文字溢出省略号
语法:.textOverflow({ overflow: Textflow.XXX })
。需要配合.maxLines(行数)
使用。
XXX的可选值有Clip、Ellipsis、None。
- 行高
语法:.lineHeight(数字)
Text("HarmonyOS开发初体验")
.fontSize(20)
.fontWeight(FontWeight.Bolder)
.width('100%')
.lineHeight(30)
Text("方舟开发框架(简称ArkTS)为HarmonyOS应用的UI开发提供了完整的基础设施,包括简洁的UI语法、丰富的UI功能(组件、布局、动画以及交互事件),以及实时界面预览工具等,可以支持开发者进行可视化界面开发。")
.textOverflow({overflow: TextOverflow.Ellipsis})
.maxLines(2)
图片组件
图片组件用于向界面中展示图片。图片的路径一般放在项目目录下的main/resources/base/media目录中。
图片组件用Image表示。若我们的图片位于本地且放在了上述目录下,那么使用图片组件的语法就是Image($r('app.media.文件名'))
。
// 使用网络上的图片
Image("https://imqi1.com/static/img/imqi1-144.png")
.width('50%')
Text("ImQi1图标")
若要使用本地图片,则需要将图片放入src/main/resources/base/media目录下,然后代码中使用$r
来引用本地图片。
Image($r("app.media.icon")).width('50%')
Text("应用图标")
输入框
输入框可以接收用户输入的文本,并将其存储到变量中。输入框使用TextInput函数,语法为TextInput({placeholder: '占位符文本'}).属性方法()
。
.type(InputType.XXX)
可以设置输入框的类型。
TextInput({placeholder: "请输入用户名"})
TextInput({placeholder: "请输入密码"}).type(InputType.Password)
按钮
按钮是可以点击的组件,创建语法是Button("按钮文本")
。
TextInput({placeholder: "请输入用户名"}).width("80%")
TextInput({placeholder: "请输入密码"}).type(InputType.Password).width("80%")
Button("登录").width("40%")
设计资源 - svg图标
svg是一种向量形式的图片,它对于png、jpg等图片格式相比,可以任意放大缩小且不失真,可以改颜色。
我们可以从鸿蒙设计官网下载图标。网址为https://developer.harmonyos.com/cn/design/harmonyos-icon/。
选好图标后,将图标复制到src/main/resources/base/media目录下,然后参照上方的语法引用即可。
布局组成
和H5界面开发一样,一个盒子由边框、内边距和组件内容组成。盒子与盒子之间还有外边距来互相隔开一段距离。
我们可以为组件添加内边距来让组件内容和边框存在一段距离,语法为.padding(距离)
。
Text("组件内容")
.fontSize(50)
.backgroundColor(Color.Gray)
.fontColor(Color.White)
.padding(20)
我们也可以为padding传入一个对象,分别设置四个方向的距离。语法如下。
Text("组件内容")
.fontSize(50)
.backgroundColor(Color.Gray)
.fontColor(Color.White)
.padding({
right: 10,
bottom: 20,
left: 30,
top: 40
})
设置外边距margin也是这样的语法,这里不再演示。
布局组成中的边框
边框的属性要更多一些,因为边框是由线条组成的,线条可以具有宽度、颜色、风格等。
设置边框的语法为.border(样式)
,其中样式需要是一个对象。
Text("设置四周同样的边框")
.padding(20)
.border({
width: 4, //设置宽度
color: Color.Red, //设置红色
style: BorderStyle.Solid //设置实线
})
初次之外,还可以为每个边框单独设置样式。
Text("四个边框单独设置")
.padding(20)
.border({
width: {
left: 2,
right: 4
},
color: {
left: Color.Red,
right: Color.Blue
},
style: {
left: BorderStyle.Dashed, //虚线
right: BorderStyle.Dotted //省略号样式
}
})
组件圆角
组件圆角的语法为.borderRadius(参数)
。参数可以使用数值,代表每个方向的圆角大小,也可以使用一个对象,单独设置每个角。对象可用的属性分别是topLeft、topRight、bottomLeft、bottomRight,分别代表四个方向。
Text("没有圆角")
.padding(20)
.backgroundColor(Color.Blue)
.fontColor(Color.White)
Text("使用数值设置圆角")
.backgroundColor(Color.Gray)
.padding(20)
.borderRadius(20)
Text("四个圆角单独设置")
.backgroundColor(Color.Green)
.borderRadius({
topLeft: 10,
topRight: 20,
bottomLeft: 30,
bottomRight: 40
}).padding(20)
.width(200)
.height(70)
背景图片
背景样式包含背景色、背景图,可以为背景图设置位置、尺寸等等。
背景图使用.backgroundImage(背景图地址[, 是否平铺])
来设置。背景图地址可以使用$r
引用资源文件夹文件,也可以使用URL引用远程地址的资源。是否平铺是一个可选参数,可选值为ImageRepeat的几个值,有X、Y、XY和NoRepeat。
Text("设置背景图")
.padding(50)
.border({
width: 1,
style: BorderStyle.Dashed
}).backgroundImage($r("app.media.icon"))
Text("设置背景图")
.padding(50)
.border({
width: 1,
style: BorderStyle.Dashed
}).backgroundImage($r("app.media.icon"), ImageRepeat.XY)
设置背景图具体位置
背景图位置使用.backgroundImagePosition(坐标对象 或 位置枚举)
来设置。
Text("设置背景图")
.padding(50)
.border({
width: 1,
style: BorderStyle.Dashed
}).backgroundImage($r("app.media.icon"))
.backgroundImagePosition({x: 100, y: 100})
也可以使用位置枚举,如让它居中。
Text("设置背景图")
.padding(50)
.border({
width: 1,
style: BorderStyle.Dashed
})
.backgroundImage($r("app.media.icon"))
.backgroundImagePosition(Alignment.Center)
Alignment的属性包含:
TopStart,
Top,
TopEnd,
Start,
Center,
End,
BottomStart,
Bottom,
BottomEnd。
单位问题与vp2px
由于不同终端的分辨率和长宽有很大差别,导致像素块大小不一致。若简单地以像素作为显示单位,则在不同终端的显示大小或比例会有很大差别。由此产生了一种虚拟像素单位vp,它相对于不同的像素会自动转换,保证不同设备视觉一致。函数vp2px用于将vp单位的长度转换为px单位的长度。
我们使用.width()
和.height()
设置长宽时,单位默认为vp;但我们设置图像时,图片背景相对位置的单位为px。于是我们可以使用vp2px函数将它们进行转换。
Text("设置背景图")
.padding(50)
.width(400)
.height(300)
.border({
width: 1,
style: BorderStyle.Dashed
})
.backgroundImage($r("app.media.icon"))
.backgroundImagePosition({
x: vp2px(200),
y: vp2px(100)
})
背景尺寸大小
设置背景尺寸大小等同于缩放背景图片,语法为.backgroundImageSize(宽高对象 或 枚举)
。参数可以选择{width: 尺寸, height: 尺寸}
,也可以使用枚举,语法为ImageSize
,可选值有:
- Contain:等比例缩放背景图,当宽或高与组件尺寸相同停止缩放;
- Cover:等比例缩放背景图至图片完全覆盖组件范围;
- Auto:默认,原图尺寸。
Text("设置背景图")
.padding(20)
.width(200)
.height(100)
.border({
width: 1,
style: BorderStyle.Dashed
})
.fontColor(Color.White)
.backgroundImage($r("app.media.bg"))
.backgroundImageSize(ImageSize.Cover)
界面开发 - 布局
线性布局
线性布局通过线性容器Column和Row创建。其中,Column内的元素沿垂直方向排列,Row内的元素沿水平方向排列。
线性布局 - 排列在主方向上的对齐方式
语法:.justifyContent(FlexAlign.XXX)
,其中XXX的可选值有:
- Start:顶部对齐,
- Center:中心对齐,
- End:底部对齐,
- SpaceBetween:第一个和最后一个元素紧贴顶部和底部,然后剩余元素在中央等距排布,
- SpaceAround:所有元素等间隔排列,非最两边的元素等距排列,最两边的元素和边隔开一半的间隔,
- SpaceEvently:所有元素和边等间隔排列。
Column({ space: 20 }) {
// Row({ space: 20 }) {
Text("")
.width(200)
.height(50)
.backgroundColor(Color.Gray)
Text("")
.width(200)
.height(50)
.backgroundColor(Color.Gray)
Text("")
.width(200)
.height(50)
.backgroundColor(Color.Gray)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Start)
// .justifyContent(FlexAlign.End)
// .justifyContent(FlexAlign.Center)
// .justifyContent(FlexAlign.SpaceBetween)
// .justifyContent(FlexAlign.SpaceAround)
// .justifyContent(FlexAlign.SpaceEvenly)
线性布局 - 排列在交叉轴方向上的对齐方式
交叉轴即元素在水平或垂直方向上的对齐方式,语法为.alignItems(参数)
,参数按照交叉轴的方向选择对应的枚举类型。
交叉轴在水平方向上使用HorizontalAlign对齐,三个枚举分别为Start、Center和End,在Column组件内使用。交叉轴在垂直方向上使用VerticalAlign对齐,三个枚举分别为Top、Center、Bottom,在Row组件内使用。
Text("")
.width(200)
.height(50)
.backgroundColor(Color.Gray)
Text("")
.width(200)
.height(50)
.backgroundColor(Color.Gray)
Text("")
.width(200)
.height(50)
.backgroundColor(Color.Gray)
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Start)
// .alignItems(HorizontalAlign.Center)
// .alignItems(HorizontalAlign.End)
Row({ space: 20 }) {
Text("")
.width(200)
.height(50)
.backgroundColor(Color.Gray)
Text("")
.width(200)
.height(50)
.backgroundColor(Color.Gray)
Text("")
.width(200)
.height(50)
.backgroundColor(Color.Gray)
}
.width('100%')
.height('100%')
.alignItems(VerticalAlign.Top)
// .alignItems(VerticalAlign.Center)
// .alignItems(VerticalAlign.Bottom)
自适应伸缩
设置了自适应伸缩的子元素和兄弟元素,会按照权重分配主轴的空间。语法为.layoutWeight(数字)
。
Row(){
Text("左侧自适应")
.layoutWeight(1)
.height(40)
.backgroundColor(Color.Green)
Text("右侧固定")
.width(80)
.height(40)
.backgroundColor(Color.Orange)
}
Row(){
Text("第一块")
.layoutWeight(1)
.height(40)
.backgroundColor(Color.Pink)
Text("第二块")
.layoutWeight(2)
.height(40)
.backgroundColor(Color.Orange)
Text("第二块")
.layoutWeight(3)
.height(40)
.backgroundColor(Color.Yellow)
}
弹性布局
弹性布局Flex用于让元素流式布局,它们可以具有一定的排列顺序、对齐方式,在元素超出宽度时还可以换行。弹性布局的语法为Flex(){ 组件 }
Flex() {
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
}
.width(400)
.height(400)
.backgroundColor("#f1f1f1")
Flex()支持传递一个对象,里面可以定义对齐方式。
Flex({
direction: FlexDirection.XXX,
justifyContent: FlexAlign.XXX,
alignItems: ItemsAlign.XXX
}) {
组件们
}
direction的可选值有Row、Column、RowReverse、ColumnReverse,分别对应从左向右、从上到下、从右到左,从下到上排列。
justifyContent的可选值有Start、Center、End、SpaceBetween、SpaceAround、SpaceEvenly,它们的效果和线性布局对应的值效果相同。
alignItems的可选值有Auto、Start、Center、End、Baseline、Stretch。
最后一个就是Flex布局的元素若超出是否换行。若不换行则元素的宽度会自适应调节。
修改Flex布局的换行规则通过Flex传入参数对象的wrap属性更改,它的值可选为FlexWrap.NoWrap或FlexWrap.Wrap。
Flex({
wrap: FlexWrap.Wrap
}) {
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
}
.width(400)
.height(400)
.backgroundColor("#f1f1f1")
绝对定位
绝对定位可以控制组件位置实现层叠效果。它参照父组件左上角进行偏移,不再占有原来的位置。
语法:.position({ x: 水平偏移量, y: 垂直偏移量 })
Column() {
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
Text()
.width(100)
.height(100)
.backgroundColor(Color.Orange)
.border({
color: Color.Red,
width: 2
})
.position({
x: 150,
y: 150
})
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
}
可以看到原来三个元素为顺序排列,但是加了position绝对定位之后,原来的位置已经不占了,然后相对于父元素的左上角向右向下平移。
层级
若多个应用了position的组件相互覆盖,有些组件会被遮住,且这些组件的排列顺序是按照声明顺序从最顶部排列到最底部。我们可以通过使用层级显式定义组件的层级位置。
语法:.zIndex(整数)
。若整数值越高,这个组件就越接近顶部。
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
Text()
.width(100)
.height(100)
.backgroundColor(Color.Orange)
.border({
color: Color.Red,
width: 2
})
.position({
x: 50,
y: 50
}).zIndex(3)
Text()
.width(100)
.height(100)
.backgroundColor(Color.Green)
.border({
color: Color.Red,
width: 2
})
层叠布局
绝对加层级定位可以很方便地为组件布局,但代码过多,层叠布局为我们提供了简洁的布局方式,可以更方便地使用绝对和层叠定位。
语法:Stack({ alignContent:Alignment.对齐方式 }){ 组件们 }
Stack({
alignContent: Alignment.Center //默认值
}) {
Text("Item1")
.width(400)
.height(400)
.backgroundColor(Color.Orange)
Text("Item2")
.width(300)
.height(300)
.backgroundColor(Color.Green)
Text("Item3")
.width(200)
.height(200)
.backgroundColor(Color.Yellow)
}
.width(600)
.height(600)
.backgroundColor(Color.Pink)
Alignment的可选值有TopStart、Top、TopEnd、Start、Center、End、BottomStart、Bottom、BottomEnd。
高级
字符串拼接
由于ArkTS为强类型语言,有很多组件要求传入的参数都为字符串,如Text()。直接将数字变量传入进去会报错,这时我们就需要将数字转换成字符串。若我们需要使用组件中的数字进行运算,我们还需要将字符串转化为数字。
字符串拼接使用 + 运算符,或使用模板字符串。+ 运算符可以直接相加两个字符串对象,模板字符串则是使用`表示字符串对象,然后在内部使用${变量}
。后者可以将字符串内部的占位符替换成具体的变量值。
let num: number = 123;
let str: string = "这是一个字符串";
console.log(`字符串的值:${str} 数字的值:${num}`) // 字符串的值:这是一个字符串 数字的值:123
若 + 旁边的两个运算对象有一个为字符串,那么得到的结果也是字符串。
类型转换
- 字符串转换为数字
Number()
:字符串,直接转为数字,若转换失败则返回NaN。(转换失败是由于字符串中含有非数字字符)parseInt()
:去掉小数部分转数字,转换失败返回NaN;parseFloat():保留小数部分,转换失败返回NaN。
实际使用时常常使用Number()转换为数字。
console.log("Number(num1)", Number(num1)) // 1.1
console.log("Number(num2)", Number(num2)) // 1.9
console.log("Number(num3)", Number(num3)) // NaN
console.log("Number(num4)", Number(num4)) // NaN
console.log("parseInt(num1)", parseInt(num1)) // 1
console.log("parseInt(num2)", parseInt(num2)) // 1
console.log("parseInt(num3)", parseInt(num3)) // 1
console.log("parseInt(num4)", parseInt(num4)) // NaN
console.log("parseFloat(num1)", parseFloat(num1)) // 1.1
console.log("parseFloat(num2)", parseFloat(num2)) // 1.9
console.log("parseFloat(num3)", parseFloat(num3)) // 1.1
console.log("parseFloat(num4)", parseFloat(num4)) // NaN
- 数字转换为字符串
toString()
:数字直接转换为字符串。toFixed()
:数字转换为字符串,可选择保留几位小数,四舍五入。
let num1: number = 1.234
let num2: number = 1234
@Entry
@Component
struct Index {
build() { // 在这里面写代码
Column() {
Text(num1.toString())
Text(num2.toString())
Text(num1.toFixed(2))
Text(num2.toFixed(2))
}
}
}
事件交互
事件交互可以让我们为组件的事件被触发后执行某些事情,比如点击一个按钮后弹出一个文字提示。
我们以最简单的点击事件为例。点击事件使用.onClick(callback)
语法,可以加在按钮上。callback为一个函数,在事件被触发时执行。
function show() {
AlertDialog.show({
message: "弹出一个文本提示"
})
}
@Entry
@Component
struct Index {
build() { // 在这里面写代码
Column() {
Row() {
Button("按钮")
.onClick(show)
}.height("100%")
}.width("100%")
}
}
状态管理
这里先引入两个概念:
- 普通变量:只在初始化时渲染,后续将不再刷新。
- 状态变量:需要装饰器装饰,改变会引起UI的渲染刷新(必须设置类型和初始值)
所以我们要改变元素的状态时,就可以通过改变状态变量的值来达到目的。
@Entry
@Component
struct Index {
@State msg: string = "Hello World!"
build() {
Row() {
Column() {
Text(this.msg)
Button("改变文字").onClick(() => {
this.msg = "你好,世界!"
})
}.width("100%")
}.height("100%")
}
}
在组件内定义的变量,无论是何种变量,都需要使用this进行访问。
let name: string = "张三";
@Entry
@Component
struct Index {
age: number = 18;
@State msg: string = "Hello World!"
build() {
Row() {
Column() {
Text(name).onClick(()=>{
name = "李四";
console.log("name: ", name) // 值被改变,但是渲染不变
})
Text(this.age.toString()).onClick(()=>{
this.age = 20;
console.log("this.age: ", this.age) // 值被改变,但是渲染不变
})
Text(this.msg).onClick(()=>{
this.msg = "你好世界";
console.log("this.msg: ", this.msg) // 值被改变,渲染也被改变
})
}.width("100%")
}.height("100%")
}
}
运算符
ArkTS中数字间可进行加减乘除和取余运算。
+
:相加,返回两个数的和。-
:相减,返回两个数的差。*
:相乘,返回两个数的积。/
:相除,返回两个数的商。%
:取余,返回两个数相除后的余数。
这五个运算符和赋值运算符=
配合,又可以组合出五个新的运算符。如+=
,num += 1
,相当于num = num + 1
。
let num: number = 7
console.log("num + 2 = ", num + 2) // 9
console.log("num - 2 = ", num - 2) // 5
console.log("num * 2 = ", num * 2) // 14
console.log("num / 2 = ", num / 2) // 3.5
console.log("num % 2 = ", num % 2) // 1
一元运算符
ArkTS有两个一元运算符:++
和--
,它们的作用相当于让变量增减一。
假设num为变量,则num++
表示先使用num的值,再让num加一。--
运算符也是这样。
let num: number = 1;
console.log("num++", num++); //1 num=2
console.log("++num", ++num); //3 num=3
console.log("--num", --num); //2 num=2
console.log("num--", num--); // 2 num=1
比较运算符
比较运算符用于比较两个数据的大小,返回一个布尔值。
>
:大于。>=
:大于等于。<
:小于。<=
:小于等于。==
:等于等于。!=
:不等于。
console.log("1>1:", 1 > 1);
console.log("1>2:", 1 > 2);
console.log("1<2:", 1 < 2);
console.log("1>=2:", 1 >= 2);
console.log("1<=2:", 1 <= 2);
==
也可以判断两个字符串字面值是否一致。
逻辑运算符
逻辑运算符用于将并列的布尔运算合并,有三个:
&&
:若两个布尔值有一个为假,则整个表达式为假。||
:若两个布尔值有一个为真,则整个表达式为真。!
:反转运算布尔值。
console.log("false && false:", false && false); // false && false: false
console.log("true && true:", true && true); // true && true: true
console.log("false && true:", false && true); // false && true: false
console.log("false || false:", false || false); // false || false: false
console.log("true || true:", true || true); // true || true: true
console.log("false || true:", false || true); // false || true: true
console.log("!false:", !false); // !false: true
console.log("!true:", !true); // !true: false
运算符优先级
运算符优先级表示互相组合的运算符运算顺序,如我们的相加和赋值操作同时存在时,先相加再赋值,是因为赋值运算符的优先级低于相加运算符的优先级。
下表表示了运算符相互组合时运算符的优先顺序,从上往下优先级递减。
优先级 | 顺序 |
---|---|
小括号 | () |
一元运算符 | ++ 、-- 、! |
算数运算符 | * 、/ 、% 先于+ 、- |
比较运算符 | > 、< 、>= 、<= |
比较运算符 | == 、!= |
逻辑运算符 | 先&& 后` |
赋值 | = |
数组的增加删除替换
操作 | 语法 |
---|---|
查找 | 数组名[下标]、数组名.length |
修改 | 数组名[下标] = 新值 |
增加 | 数组名.push(数据1, 数据2, ...)、数组名.unshift(数据1, 数据2, ...) 前者为像数组的末尾追加值,后者为向数组的开始增加值 |
删除 | 数组名.pop()、数组名.shift() |
任意位置删除或增加 | 数组名.splice(操作的起始位置, 删除的个数, 新增1, 新增2) |
// 数组的查看和修改
// 1. 定义一个数组
let names: string[] = ['刘小备', '吕小布', '张大飞']
console.log('整个数组',names)
// 2. 数组取值(通过下标)
console.log('数组取值', names[1])
console.log('数组长度', names.length)
// 3. 数组修改(通过下标)
names[2] = '赵云'
console.log('修改数组', names)
// 数组的增加和删除
// 定义一个数组
let songs: string[] = ['告白气球', '洋葱', '吻别']
// 添加
// 1. 往开头新增 unshift(新增的值) 返回操作后的数组的长度
songs.unshift('彩虹')
console.log('返回数组长度', songs.unshift('七里香'))
console.log('数组songs', songs)
// 2. 往结尾新增 push(新增的值) 返回操作后的数组的长度
songs.push('光辉岁月', '海阔天空')
console.log('数组', songs)
// 删除
// 1. 从开头删 shift
console.log('返回删除的项', songs.shift())
console.log('返回删除的项', songs.shift())
console.log('数组', songs)
// 2. 从结尾删 pop
songs.pop()
songs.pop()
songs.pop()
console.log('数组', songs)
// 开头(S): unshift(开头增) shift(开头删)
// 结尾(P): push(结尾增) pop(结尾删)
// 在任意位置删除数组元素
// 定义一个数组
let songs: string[] = ['告白气球', '洋葱', '吻别', '双节棍', '曹操']
// splice 在任意位置进行删除或新增内容
// 数组名.splice(操作的起始位置, 删除几个, 新增的项1, 新增的项2, ...)
// 1. 删除(任意位置)
songs.splice(2, 2)
console.log('数组songs', songs)
// 2. 新增(任意位置)
songs.splice(1, 0, '彩虹') // 新增
// 3. 替换(删了一项, 又加了一项)
songs.splice(1, 1, '彩虹')
console.log('数组songs', songs)