本节记录通过黑马程序员B站课程学习鸿蒙应用开发的笔记。
黑马程序员鸿蒙课程
课程内容:
-
- 鸿蒙APP开发
- (1)ArkUI界面与交互
- (2)组件化开发
- (3)网络管理
-
- 能力套件开发
- (1)一次开发多端部署
- (2)系统能力集
- (3)开放能力集
-
- 全场景开发
- (1)元服务
- (2)端云一体化
- (3)万物互联
1. ArkTS基础快速入门
console.log() 在日志里打印东西
-
三种基础数据类型
-
- string
-
- number
-
- boolean
-
-
存储数据
//let 变量名:类型 = 值
let title : string = "奥利奥"
let price : number = 10
let isBuy : boolean = true
//const 常量名:类型 = 值
const PI: number = 3.1415926
//命名规则
//1. 只能包含数字,字母,下划线和 $, 不能以数字开头
//2. 不能使用关键字和保留字
//3. 区分大小写
- 数组
//let 变量名:类型[] = [值1,值2,值3]
let arr : number[] = [1,2,3,4,5]
//取数据
console.log(arr[0])
//修改数据
arr[0] = 100
//添加数据
arr.push(6)
//删除数据
arr.pop()
- 函数
//function 函数名(参数1:类型,参数2:类型):返回值类型{
// 函数体
//}
function sum(a:number,b:number):number{
return a+b
}
console.log(sum(1,2))
- 箭头函数
//let 函数名 = (参数1:类型,参数2:类型):返回值类型 => {
// 函数体
//}
- 接口&对象 对象方法
//interface 接口名{
// 属性1:类型1
// 属性2:类型2
// 属性3:类型3
// 方法名:(参数:类型) => 返回值类型
//}
interface Person{
name:string
age:number
weight:number
dance:() => void
sing:(song:string) => void
}
let person1:Person = {
name:"张三",
age:18,
weight:60
dance(){
console.log("跳舞")
},
sing(song:string){
console.log("唱歌",song)
}
}
- 联合类型
//let 变量名:类型1 | 类型2 | 类型3 = 值
let a:number | string = 10
a = "hello"
//let 变量名: 具体值1 | 具体值2 | 具体值3 = 值
let gender : "男" | "女" | "保密"= "男"
- 枚举类型 (使用更多)
- 数组操作
- 增加元素
数组.push(元素1,元素2)
在数组末尾添加元素数组.unshift(元素1,元素2)
在数组开头添加元素
- 删除元素
数组.pop()
删除数组末尾元素数组.shift()
删除数组开头元素
- 任意位置增删元素
数组.splice(起始位置,删除个数,新增元素1,新增元素2)
删除元素并添加元素
- 增加元素
- 遍历数组:for … of
for(let item of 数组){}
- 对象数组:输出
console.log(JSON.stringify(对象数组))
//enum 枚举名{
// 枚举值1 = 具体值1,
// 枚举值2 = 具体值2,
// 枚举值3 = 具体值3
// }
enum color{
Red = '#ff0f29',
Orange = '#ff7100',
Green = '#30b30e'
}
- 字符串拼接&模板字符串
let name = "张三"
let age = 18
let str = name + "今年" + age + "岁"//字符串拼接
let str = `${name}今年${age}岁`//模板字符串,更适合复杂场景,注意使用反引号
- class类
- instanceof : 检测某个对象是否是某个类的实例
- typeof : 检测数据类型(只能判断简单类型)
- 修饰符:readonly,private,protected,public)
class 子类 extends 父类{
字段A:类型
字段B:类型
static 字段C:类型
constructor(参数1:类型,参数2:类型,...){
this.字段A = 参数1
this.字段B = 参数2
super(...)
}
方法1(参数:类型):返回值类型{
return ...
}
static 方法2(参数:类型):返回值类型{
return ...
}
//重写方法只需同名即可,子类通过super调用父类方法,属性
}
- 剩余参数和展开运算符
function 函数名(参数1,参数2,...剩余参数数组){...}
//展开运算符只能用在数组上
let arr1 = [1,2,3]
let arr2 = [4,5,6]
let arr3 = [...arr1,...arr2]
- 接口继承与实现
interface 父接口{
属性1:类型
属性2:类型
方法1:(参数:类型) => 返回值类型
}
interface 子接口 extends 父接口{
属性3:类型
方法2:(参数:类型) => 返回值类型
}
class 类名 implements 子接口{
属性1:类型
属性2:类型
属性3:类型
方法1(参数:类型):返回值类型{
return ...
}
方法2(参数:类型):返回值类型{
return ...
}
}
- 泛型
- 泛型函数
- 泛型约束:对传递参数类型限制
- 多个泛型参数
- 泛型接口
- 泛型类
// 1. 泛型函数
function 函数名<Type>(temp:Type):Type{
return temp
}
函数名<number>(10)
函数名<string>("hello")
// 2. 泛型约束
interface 约束类型{
length:number
}
function 函数名<Type extends 约束类型>(temp:Type):Type{
return temp.length
}
// 3. 多个泛型参数
function 函数名<Type1,Type2>(temp1:Type1,temp2:Type2):Type1{...}
函数名<number,string>(10,"hello")
// 4. 泛型接口,泛型类
interface 接口名<Type>{
属性1:Type
方法1:(参数:Type) => Type
}
class 类名<Type> implements 接口名<Type>{
属性1:Type
方法1(参数:Type):Type{
return ...
}
}
- 模块化:ArkTs中每个ets文件可看作一个模块
- 默认导出/入:一个模块,只能默认到处 一个值或对象
- 按需导出/入:
- 全部导入:
// 1. 默认导出(只能导一个)
export default 值 //导出
import 变量名 from '文件相对路径' // 导入
// 2. 按需导出或导入
export {值1,值2,值3} //导出
export function 函数名(){...}
export class 类名{...}
import {值1,值2,值3 as 别名} from '文件相对路径' //导入
// 3. 全部导入
export {值1,值2,值3}
export * from '文件相对路径'
import * as 变量名(一个对象) from '文件相对路径'
2. 界面开发入门
2.1 界面架构
- ArkUI(方舟开发框架)是一套构建鸿蒙应用界面的框架
- 构建页面最小单位是 “组件”
- 基础组件:界面呈现的基础元素。如文本、图片、按钮等
- 容器组件:用于布局的容器。如栈布局、网格布局等
- 界面开发布局思路:先排版后放内容,再美化
- 组件的属性方法
//属性
//组件(){}
//.属性方法1(参数)
//.属性方法2(参数)
- 字体颜色
.fontColor(颜色值)
- 文字溢出省略号
Text('方舟...')
.textOverflow({
overflow:TextOverflow.Ellipsis //选择溢出枚举类
})
.maxLines(2)//设置溢出的最大行数
.lineHeight(40)//设置行高
- 图片组件
Image(图片数据源)
- 网图
Image("https://xxx")
- 本地图片
Image($r('app.media.xxx))
- 网图
- 输入框和按钮
TextInput(参数对象)
.属性方法
Button(参数对象)
- 设计资源-svg图标(任意放大缩小,不失真,可以改颜色)
- 使用方式
-
- 设计师提供,相当于本地文件
-
- 图标库选取(选择官方的图标图贴合程度高)
-
- 使用方式
- 布局元素的组成
- 内边距padding
- 外边距margin
- 边框border
.padding({
left:20,
top:30,
right:40,
bottom:50
})//四个方向的内边距
.padding(30)//四个方向都是30
.margin({
left:20,
top:30,
right:40,
bottom:50
})//四个方向的外边距
.margin(30)//四个方向都是30
.border({
width:1,
color:'#000000',
style:BorderStyle.Solid
})
.border({
width:{
left:1,
top:2,
right:3,
bottom:4
},
color:{
left:'#ff0000',
top:'#00ff00',
right:'#0000ff',
bottom:'#000000'
},
style:{
left:BorderStyle.Solid,
top:BorderStyle.Dashed,
right:BorderStyle.Dotted,
bottom:BorderStyle.Dotted
}
})
- 设置组件圆角
.borderRadius(10)
.borderRadius({
topLeft:10,
topRight:20,
bottomLeft:30,
bottomRight:40
})
// 特殊圆角
//1 正圆
Text('正圆')
.width(100)
.height(100)
.borderRadius(50)
//2. 胶囊按钮
Text('胶囊按钮')
.width(150)
.height(100)
.borderRadius(50) // 圆角是高的一半
- 背景属性
- backgroundColor
- backgroundImage(配置图片(同Image用法),是否平铺ImageRepeat.XY)
- .backgroundImagePosition({x:100,y:100})
- .backgroundImagePosition(Alignment.Center)
- .backgroundImageSize(宽高对象 或 枚举)
- 线性布局:Column布局和Row布局
//主轴对齐方式
.justifyContent(Alignment.XXX)
//1. Start 主轴起始位置对齐
//2. Center 主轴中间位置对齐
//3. End 主轴结束位置对齐
//4. SpaceBetween 贴边显示,中间的元素间距相等
//5. SpaceAround 间隙环绕,顶和底间隙一半,中间的元素间距相等
//6. SpaceEvenly 间隙均匀,所有间距相等
//交叉轴对其方式
.alignItems()
//alignItems(HorizontalAlign.XXX)
//alignItems(VerticalAlign.XXX)
- 自适应伸缩
.layoutWeight(数字) //按照权重分配主轴的空间
- 弹性布局(Flex)
- 主轴方向 direction
- 主轴对齐方式 justifyContent
- 交叉轴对齐方式 alignItems
- 布局换行 wrap
Flex({
direction:FlexDirection.Row,
justifyContent:Alignment.Center,
alignItems:Alignment.Center,
wrap:FlexWrap.Wrap//多行布局
}){}
- 绝对定位
- 作用:控制组件位置,实现层叠效果
- 特点:参照父组件左上角进行偏移;不占用原有位置
- 语法:.position(位置对象)
- 参数:
- 覆盖层级:
- 默认情况下,后添加的组件会覆盖前面的组件
- 可以通过zIndex(参数)属性设置层级,参数越大层级越高
- 层叠布局:层叠操作更简介,编码效率更高
Stack(){
alignContent:Alignment.XXX//包括9宫格9种形式
}{
Item1()
Item2()
Item3()
}
2.2 事件处理
- 类型转换
- 字符串转数字
parseInt(字符串)
去除小数部分,parseFloat(字符串)
保留小数部分,Number(字符串)
- 数字转字符串
数字.toString()
,.toFixed(x)
四舍五入转字符串,可以设置保留x位
- 字符串转数字
- 点击事件
- 说明:组件被点击时触发的事件
- 作用:监听用户的点击行为,进行对应操作
- 语法:
onClick((参数)=>{})
- 状态管理
- 普通变量:只能在初始化时渲染,即使改变后续不再刷新
- 状态变量:需要装饰器(@State)修饰,改变会引起UI的渲染刷新
- ForEach渲染控制:
- 说明:遍历数组,基于数组元素渲染组件
- 语法:
ForEach(数组,(元素,索引)=>{})
- Badge角标组件:
- Grid布局:网格布局
- Swiper轮播组件
- 基本属性
- 常见属性:loop,autoplay,interval等
- 样式自定义(定制小圆点):.indicator
Swiper(){
Image()
Image()
Image()
}
.indicator(
Indicator.dot()
)
.loop(true)
.width()
.height()
- 样式和结构的重用
@Extend
:扩展组件的 样式,事件,实现复用效果@Styles
:样式抽取,针对通用属性@Builder
:自定义构建函数(结构,样式,事件)@Styles
和@Builder
可以在组件内部定义,局部复用,使用this关键字
@Extend(组件)//以组件为单位
function MyComponentFn(参数){
//组件内容
.width()
.onClick()
}
组件.MyComponentFn(参数)
@Styles function MyStyle(){ //以样式为单位,不特定于组件,不支持传参
//样式内容
.width()
.onClick()
}
@Builder function MyBuilder(参数){
//组件内容
Column(){...}
.width()
.onClick()
...
}
Row(){
MyBuilder(参数1)
MyBuilder(参数2)
}
- 滚动容器Scroll
- 用法:设置尺寸,设置溢出组件,滚动方向
- 常见属性:滚动条状态,颜色,宽度,边缘滑动效果
- 控制器:控制滚动位置,获取滚动距离
- Scroll事件:
- 容器组件Tabs:分类展示
- 基本用法
- 常用属性:调整位置(上下,横纵),动画
- 滚动导航栏:.scrollable(true)
- 自定义TabBar:使用@Builder ,高亮切换
Tabs(){
TabContent(){}
.tabBar("A")
TabContent(){}
.tabBar(this.MyTabBar(参数))
}
@Builder MyTabBar(参数){
Row(){
Text()
Text()
Text()
}
}
- List容器组件:
- 当List容器组件超过范围时,可自动滚动
- 主轴方向,交叉轴布局(列数,间距),列对齐方式,振动条状态,分割线样式
List(){
ForEach(Array.from({length:20}),()=>{
ListItem(){
Row(){}.width(300).height(100).backgroundColor(Color.Red)
}
.padding(10)
})
}
.width("100%")
.layoutWeight(1)
.backgroundColor(Color.Orange)
3. 组件化开发
- 概念:由框架直接提供的组件成为系统组件,由开发者定义的为 自定义组件
- 自定义组件也可以通过 .语法设置 通用事件,样式
- 组件可以有成员变量即成员函数
- 成员变量:外部可传参覆盖(带等号的都是成员变量)
- 成员函数不可覆盖
@Component
struct HelloCompont{
//状态变量
@State msg:string = ""
//成员变量-数据
info:string = ""
//成员变量-函数
sayHello = ()=>{}
//成员函数
sayHi(){}
//描述UI
...
}
@Entry
@Component
struct Main{
build(){
//调用HelloCompont
HelloCompont()
//覆盖HelloCompont的msg,info
HelloCompont({info:"你好",msg:"你好"})
//覆盖HelloCompont的sayHello
HelloCompont({sayHello(){...}})
}
}
- @BuilderParam传递UI
@Component
struct SonCom{
//定义构建函数
@BuilderParam ContentBuilder:()=>void = this.defaultBuilder
// @BuilderParam TitleBuilder:()=>void = this.TitledefaultBuilder
// @Builder
// TitledefaultBuilder(){
// Text("默认标题")
// }
@Builder
defaultBuilder(){
Text("默认内容")
}
build(){
Column(){
// 使用构建函数
this.ContentBuilder()
}
}
}
@Entry
@Component
struct Main{
// 多@BuilderParam情况
// @Builder
// contentBuilder(){
// Text("自定义")
// }
// @Builder
// titleBuilder(){
// Text("自定义")
// }
build(){
Column(){
SonCom(){
Text("自定义内容")
}
//多@BuilderParam情况
// SonCom({
// ContentBuilder:this.contentBuilder,
// TitleBuilder:this.titleBuilder
// })
}
}
}
- 状态管理
@State
:自己的状态。不是所有的状态变量的改变都会引起刷新,只有被框架观察到的修改才会引起UI刷新-
- boolean,string,number可以观察到数据的变化
-
- class或Object时,可以观察到自身赋值的变化,第一层属性赋值的变化,即Object.keys(observedObject)的变化
-
@Prop
:父子单向-
- 其装饰的变量可以和父组件建立单向的同步关系
-
- 装饰的变量是可变的,但是变化不会同步到父组件
-
- 如果想在子组件中改父组件的变量,可以通过传入父组件的方法
-
@Link
:同上,但是双向传递@Provide,@Consume
:- 跨组件传递,进行数据同步
- 父组件使用@Provide提供数据,子组件使用@Consume消费数据
@Component
struct SonCom{
//保证父组件的数据变化了,向下响应式更新
//子组件可以修改info,但是不会影响父组件
@Prop info:string
//@Link info:string
//@Consume info:string
changeinfo = (newInfo:string) =>{}
build() {
Column(){
Button("info:"+this.info)
.onClick(()=>{
this.changeinfo("更改成功")
})
Button("子组件换")
.onClick(()=>{
this.info = "fgd"
})
}
}
}
@Entry
@Component
struct FatherCom{
@State info:string = "👍"
//@Provide info:string = "👍"
build() {
Column(){
Text(this.info)
SonCom({
info:this.info,
changeinfo:(newInfo:string) =>{this.info = newInfo}
})
}
}
}
- @Observed 与 @ObjectLink
- 说明:装饰器只能观察到 第一层的变化
- 作用:用于 涉及嵌套对象或数组 的场景中进行 双向数据同步;深层传递,可以减少整个组件的刷新
- 机理:使用@Observed修饰的数据改变时,会遍历所有依赖的@ObjectLink数据,通知数据更新
@Observed class XXX{}
父组件中使用 @State
子组件中使用 @ObjectLink
- 路由
-
- 创建页面
- (1)在项目中通过new选项新建页面
- (2)新建普通ets文件,配置成页面(在main_pages.json中)
-
- 页面跳转和后退
-
- 页面栈
-
- 路由模式:提供两种不同的跳转模式
- Standard:无论之前是否有相同页面,都会新建一个页面
- Single:如果之前有相同页面,会将已有的同url页面移动到栈顶
-
- 路由传参
-
// 2. 跳转
import {Router} from '@ohos.router'
// 普通跳转
router.pushUrl({
uri:'pages/xxx/xxx'
})
// 替换跳转
router.replaceUrl({
uri:'pages/xxx/xxx'
})
// 返回
router.back()
// 3. 页面栈,最大容量32个页面
router.getLength()//获取页面栈长度
router.clear()//清空页面栈
// 4. 路由模式
router.pushUrl({uri:'pages/xxx/xxx',},router.RouterMode.Single)
// 5. 路由传参
// 传递参数
router.pushUrl({
uri:'pages/xxx/xxx',
params:{
key1:value1,
key2:value2
}
})
// 接收参数
const params = router.getParams()
- 生命周期
- 组件和页面在创建,显示,销毁的一整个过程中,会自动执行一系列的生命周期钩子(即一些列函数,让开发者在特定阶段运行自己的代码)
- 区分页面和组件:
@Entry
aboutToAppear(){}//创建组件实例后执行,可以修改状态变量
aboutToDisappear(){}//销毁组件实例前执行,不可以修改状态变量
// 以下仅页面有
onPageShow(){}//页面显示时执行(路由过程,应用进入前后台)
onPageHide(){}//页面隐藏时执行(路由过程,应用进入前后台)
onBackPress(){}//返回键按下时执行(return true阻止返回键默认返回效果)
-
Stage模型
- 应用模型是系统为开发者提供的应用程序所需能力的抽象提炼,即 应用的施工图纸,规范化了:程序运行流程,项目结构,文件功能等
- UIAbility组件:
- 每一个UIAbility实例,都对应于一个最近任务列表中的任务
- UIAbility是一种包含用户界面的应用组件,主要用户和用户进行交互
- UIAbility组件的生命周期
- onCreate
- onDestory
- onForeground
- onBackground
- 同模块Ability拉起
- 跨模块Ability拉起
-
目录概览:
-
AppScope/app.json5:应用的全局配置信息
-
entry:HarmonyOS工程模块,编译构建生成一个HAP包
- src/main/ets:存放ArkTS源码
- entryability:应用/服务入口
- pages:页面
- src/main/resources:资源文件
- src/main/moudle.json5:模块配置文件(配置 ability入口图标和标签配置)
- build-profile.json5:当前模块信息,编译信息配置项,包括buildOption,targets配置等
- hvigorfile.ts:模块级编译构建任务脚本
- obfuscation-rules:txt:混淆配置文件
- src/main/ets:存放ArkTS源码
-
oh_modules:存放第三方库依赖信息
-
build-profile.json5:应用级配置信息,包括签名,产品配置等
-
hvigorfile.ts:应用级编译构建任务脚本