本节记录通过黑马程序员B站课程学习鸿蒙应用开发的笔记。
黑马程序员鸿蒙课程

课程内容:

    1. 鸿蒙APP开发
    • (1)ArkUI界面与交互
    • (2)组件化开发
    • (3)网络管理
    1. 能力套件开发
    • (1)一次开发多端部署
    • (2)系统能力集
    • (3)开放能力集
    1. 全场景开发
    • (1)元服务
    • (2)端云一体化
    • (3)万物互联

1. ArkTS基础快速入门

console.log() 在日志里打印东西

  • 三种基础数据类型

      1. string
      1. number
      1. 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图标(任意放大缩小,不失真,可以改颜色)
    • 使用方式
        1. 设计师提供,相当于本地文件
        1. 图标库选取(选择官方的图标图贴合程度高)
  • 布局元素的组成
    • 内边距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刷新
        1. boolean,string,number可以观察到数据的变化
        1. class或Object时,可以观察到自身赋值的变化,第一层属性赋值的变化,即Object.keys(observedObject)的变化
    • @Prop:父子单向
        1. 其装饰的变量可以和父组件建立单向的同步关系
        1. 装饰的变量是可变的,但是变化不会同步到父组件
        1. 如果想在子组件中改父组件的变量,可以通过传入父组件的方法
    • @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. 创建页面
      • (1)在项目中通过new选项新建页面
      • (2)新建普通ets文件,配置成页面(在main_pages.json中)
      1. 页面跳转和后退
      1. 页面栈
      1. 路由模式:提供两种不同的跳转模式
      • Standard:无论之前是否有相同页面,都会新建一个页面
      • Single:如果之前有相同页面,会将已有的同url页面移动到栈顶
      1. 路由传参
// 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:混淆配置文件
  • oh_modules:存放第三方库依赖信息

  • build-profile.json5:应用级配置信息,包括签名,产品配置等

  • hvigorfile.ts:应用级编译构建任务脚本