ArkUI(方舟开发框架)是一套 构建 鸿蒙应用 界面 的框架。

构建页面的最小单位就是 "组件"

组件分类:

① 基础组件:界面呈现的基础元素

如:文字Text()、图片、按钮等。

② 容器组件:控制布局排布

如:Row行、Column列等。

调整组件之间的距离给外层容器组件加 { space: 数字 }

Column({ space: 20}){...}

布局思路

先排版,再放内容。

注意:build有且只能有一个根元素,且是容器组件

排版 → 内容 → 美化

组件

组件的属性方法

需求:美化组件外观效果 组件的属性方法

组件() {}
  .属性方法1(参数)

  .属性方法2(参数)

  .属性方法3(参数)

  ……

Text('小说简介')
 .height(40)
 .fontSize(20)
 ……

字体颜色

语法:.fontColor(颜色值)

① 枚举颜色 Color.颜色名

Color.Red、Color.Pink

② #开头的16进制

'#8fbce7' 【设计图会标注】

文字溢出省略号、行高

1. 文字溢出省略 (设置文本超长时的显示方式)

语法:.textOverflow({
  overflow: TextOverflow.XXX
})

注意:需要配合 .maxLines(行数) 使用

2. 行高

语法:.lineHeight(数字)

Text('方舟...')
 .textOverflow({
   overflow: TextOverflow.Ellipsis
 })
 .maxLines(2)
 .lineHeight(30)

Image 图片组件

作用:界面中展示图片

语法:Image(图片数据源) 支持 网络图片资源 和 本地图片资源

Image('url')
Image( $r('app.media.文件名') )

输入框 与 按钮

TextInput(参数)
  .属性方法()
1.参数:placeholder提示文本
TextInput({
  placeholder: '占位符文本'
})
2. 属性:type(InputType.xxx) 设置输入框 type 类型
① Normal 基本输入模式,无特殊限制
② Password 密码输入模式
TextInput({placeholder: '占位符文本'})
  .type(InputType.Password)
Button('按钮文本')

设计资源-svg图标

需求:界面中展示图标 → 可以使用 svg 图标(任意放大缩小不失真、可以改颜色)

使用方式:

1. 设计师提供:基于项目设计的图标,拷贝到项目目录使用

2. 图标库中选取:找合适的图标资源 → 下载(svg) 拷贝使用

HarmonyOS图标库

Image($r('app.media.ic_dianpu'))
  .width(40)//修改大小
  .fillColor('#b0473d')//修改颜色

布局元素的组成

内边距 padding

作用:在 组件内 添加 间距,拉开内容与组件边缘之间的距离

Text('内边距padding')
  .padding(20) // 四个方向内边距均为20
Text('内边距padding')
  .padding({
    top: 10,
    right: 20,
    bottom: 40,
    left: 80
}) // 四个方向内边距分别设置

外边距 margin

作用:在 组件外 添加 间距,拉开两个组件之间的距离

Text('外边距margin')
  .margin(20) // 四个方向外边距均为20
Text('外边距margin')
  .margin({
    top: 10,
    right: 20,
    bottom: 40,
    left: 80
}) // 四个方向内边距分别设置

边框 border

作用:给组件添加边界,进行装饰美化

Text('边框语法')
  .border({
    width: 1, // 宽度
    color: '#3274f6', // 颜色
    style: BorderStyle.Solid // 样式
}) // 四个方向相同
Text('边框语法')
  .border({
    width: { left: 1 },
    color: { left: 'red' },
    style: { left: BorderStyle.Dashed }
}) // top、right、bottom、left

设置组件圆角

属性:.borderRadius(参数)

参数:数值 或 对象 (四个角单独设置)

topLeft:左上角

topRight:右上角

bottomLeft:左下角

bottomRight:右下角

Text('圆角语法')
  .borderRadius(5) // 四个圆角相同
  .borderRadius({
    topLeft: 5,
    topRight: 10,
    bottomRight: 15,
    bottomLeft: 20
}) // 四个方向圆角,单独设置

特殊形状的圆角设置

1. 正圆

Text('正圆')
  .width(100) // 宽度高度一样
  .height(100)
  .borderRadius(50) // 圆角是宽或高的一半

2. 胶囊按钮(左右半圆)

Text('胶囊按钮')
  .width(150) // 宽度大,高度小
  .height(50)
  .borderRadius(25) // 圆角是高的一半

背景属性

背景图 - backgroundImage

属性:.backgroundImage(背景图地址)

Text()
  .backgroundImage($r('app.media.flower'))

背景图平铺方式-枚举ImageRepeat

背景图平铺方式:(可省略)

NoRepeat:不平铺,默认值

X:水平平铺

Y:垂直平铺

XY:水平垂直均平铺

Text('我是文本')
   .backgroundImage($r('app.media.flower'),ImageRepeat.XY)

背景图位置 - backgroundImagePosition

作用:调整背景图在组件内的显示位置,默认显示位置为组件左上角

属性:.backgroundImagePosition(坐标对象 或 枚举)

参数:

位置坐标: { x: 位置坐标, y: 位置坐标 } (单位下一节详细说)

枚举 Alignment

Text()
  .backgroundImage($r('app.media.flower'))
  .backgroundImagePosition({ x: 100, y:100 })
  .backgroundImagePosition(Alignment.Center)

背景图尺寸 - backgroundImageSize

作用:背景图缩放

属性:.backgroundImageSize(宽高对象 或 枚举)

参数:

背景图宽高:{ width: 尺寸, height: 尺寸 }

枚举 ImageSize

Contain:等比例缩放背景图,当宽或高与组件尺寸相同停止缩放

Cover:等比例缩放背景图至图片完全覆盖组件范围

Auto:默认,原图尺寸

Text()
  .backgroundImage($r('app.media.flower'))
  .backgroundImageSize({ width: 250, height: 100 })
  .backgroundImageSize(ImageSize.Cover)

单位问题

背景定位默认单位 → px:实际的物理像素点,设备出厂,就定好了【分辨率单位】

宽高默认单位 → vp虚拟像素,相对于不同的设备会自动转换,保证不同设备视觉一致 (推荐)

函数:vp2px(数值) 将vp进行转换,得到px的数值

Badge 角标组件

Badge({
  count: 1, // 角标数值
  position: BadgePosition.RightTop, // 角标位置
  style: {
    fontSize: 12, // 文字大小
    badgeSize: 16, // 圆形大小
    badgeColor: '#FA2A2D' // 圆形底色
  }
}) {
Image($r('app.media.bg_01'))
  .width(80)
}

类似于消息产生的小红点

Swiper 轮播组件

Swiper是一个 容器组件,当设置了多个子组件后,可以对这些 子组件 进行轮播显示。(文字、图片...)

Swiper 的基本用法

语法结构:

Swiper() {
// 1. 轮播内容
  Text('1')
  Text('2')
  Text('3')
}
// 2. 设置尺寸(内容会自动拉伸)
.width('100%')
.height(100)

Swiper() {
// 1. 轮播内容
  Image($r('...'))
  Image($r('...'))
  Image($r('...'))
}
// 2. 设置尺寸(内容会自动拉伸)
.width('100%')
.height(100)

Swiper 的常见属性

Swiper 样式自定义

Swiper() {
...
}
.indicator(
Indicator.dot() // 小圆点
 .itemWidth(20) // 默认的宽
 .itemHeight(20) // 默认的高
 .color(Color.Black) // 默认的颜色
 .selectedItemWidth(30) // 选中的宽
 .selectedItemHeight(30) // 选中的高
 .selectedColor(Color.White) // 选中的颜色
)

样式&结构重用

@Extend:扩展组件(样式、事件)

@Styles: 抽取通用属性、事件

@Builder:自定义构建函数(结构、样式、事件

@Extend:扩展组件(样式、事件)

可以将

Swiper() {
 Text('1')
  .textAlign(TextAlign.Center)
  .backgroundColor(Color.Red)
  .fontColor(Color.White)
  .fontSize(30)
  .onClick(() => {
   AlertDialog.show({
   message: '轮播图 1'
 })
})
Text('2')
 .textAlign(TextAlign.Center)
 .backgroundColor(Color.Orange)
 .fontColor(Color.White)
 .fontSize(30)
 .onClick(() => {
 AlertDialog.show({
  message: '轮播图 2'
  })
 }) ...
}

优化为

@Extend(Text)
function textExtend(color: ResourceColor, txt: string) {
  .textAlign(TextAlign.Center)
  .backgroundColor(color)
  .fontColor(Color.White)
  .fontSize(30)
  .onClick(() => {
    AlertDialog.show({
    message: txt
  })
 })
}

Swiper() {
 Text('1')
  .textExtend(Color.Red, '轮播图1')
 Text('2')
  .textExtend(Color.Orange, '轮播图2')
 Text('3')
  .textExtend(Color.Grey, '轮播图3')
}

@Styles: 抽取通用属性、事件

可以将

Text(this.message)
  .width(100)
  .height(100)
  .backgroundColor(this.bgColor)
  .onClick(() => {
     this.bgColor = Color.Orange
})
Button('按钮')
  .width(100)
  .height(100)
  .backgroundColor(this.bgColor)
  .onClick(() => {
     this.bgColor = Color.Orange
})
Column() {}
  .width(100)
  .height(100)
  .backgroundColor(this.bgColor)
  .onClick(() => {
     this.bgColor = Color.Orange
})

优化为

// 1. 全局定义
@Styles function commonStyles() {
  .width(100)
  .height(100)
  .onClick(()=>{
// ...
  })
}
@Component
struct FancyDemo {
// 2. 在组件内定义
 @Styles setBg() {
  .backgroundColor(Color.Red)
}
builder(){
 Text()
  .commonStyles()
  .setBg()
 }
}

@Builder:自定义构建函数(结构、样式、事件)

可以将

Row() {
 Column({ space: 10 }) {
 Image($r('app.media.ic_reuse_01')).width('80%')
 Text('阿里拍卖')
}
.width('25%')
.onClick(() => {
  AlertDialog.show({
  message: '点了 阿里拍卖'
 })
})
Column({ space: 10 }) {
 Image($r('app.media.ic_reuse_02')).width('80%')
 Text('菜鸟')
}
.width('25%')
.onClick(() => {
    AlertDialog.show({
    message: '点了 菜鸟'
  })
 })
}

优化为

// 全局 Builder
@Builder
function navItem(icon: ResourceStr, text: string) {
 Column({ space: 10 }) {
 Image(icon)
  .width('80%');
  Text(text);
}
 .width('25%')
 .onClick(() => {
    AlertDialog.show({
    message: '点了' + text
  })
 })
}
Row() {
 navItem($r('app.media.ic_reuse_01'),'阿里拍卖')
 navItem($r('app.media.ic_reuse_02'),'菜鸟')
}

局部 builder 类似,只是定义在组件内,this.xxx()

滚动容器 Scroll

滚动容器 Scroll

当子组件的布局尺寸 超过Scroll的尺寸 时,内容可以滚动

滚动容器 Scroll – 核心用法

用法说明:

1. Scroll 设置尺寸

2. 设置溢出的子组件(只支持一个子组件

3. 滚动方向(支持横向和纵向,默认纵向)

Scroll(){
 // 只支持一个子组件
 Column(){
 // 内容放在内部
 // 尺寸超过 Scroll 即可滚动
 }
}
.width('100%')
.height(200)
.scrollable(ScrollDirection.xxx)

滚动容器 Scroll – 常见属性

滚动容器 Scroll – 控制器

核心步骤:

1. 实例化 Scroller 的 控制器

2. 绑定给 Scroll 组件

3. 控制器的方法 控制滚动,控制器属性 获取滚动距离

struct ScrollDemo {
  scroller: Scroller = new Scroller()
  build() {
    Column() {
      Scroll(this.scroller) { ... }
      Row() {
        Button('返回顶部')
          .onClick(() => {
            this.scroller.scrollEdge(Edge.Top)
         })
        Button('获取滚动距离')
         .onClick(() => {
          const x = this.scroller.currentOffset().xOffset
          const y = this.scroller.currentOffset().yOffset
          AlertDialog.show({
           message:`x:${x},y:${y}`
         })
        })
      }
    }
  }
}

滚动容器 Scroll – Scroll 事件

Scroll 组件提供了一些事件,让开发者可以在适当的时候添加逻辑

Scroll(){
 // 内容略
}
.onScroll((x,y)=>{
 // 滚动时 一直触发
 // 可以结合 scroller的currentOffset方法 获取滚动距离
})

容器组件 Tabs

容器组件 Tabs

当页面内容较多时,可以通过Tabs组件进行 分类展示

容器组件 Tabs – 基本用法

struct TabbarDemo {
  build() {
  // 外层顶级容器
 Tabs() {
   TabContent() {
   // 内容区域:只能有一个子组件
   Text('首页内容')
 }
 .tabBar('首页') // 导航栏
 TabContent() {
  Text('推荐内容')
 }
   .tabBar('推荐')
   ...
  }
 }
}

容器组件 Tabs – 常用属性

barPosition :调整位置 开头 或 结尾 (参数)

vertical :调整导航 水平 或 垂直

scrollable :调整是否 手势滑动 切换

animationDuration :点击滑动动画时间

// BarPosition.Start 起始
// BarPosition.End 结尾
Tabs({ barPosition: BarPosition.End }) {
// 内容略
}
.vertical(true)// 垂直导航 true / 水平false
.scrollable(true) // 允许滑动 true / 不允许 false
.animationDuration(0) // 切换动画的时间,毫秒

容器组件 Tabs – 滚动导航栏、

如果导航栏的内容较多,屏幕无法容纳时,可以将他设置为滚动

可以通过 Tabs 组件的 barMode 属性即可调整 固定导航栏 滚动导航栏

Tabs(){
 // 内容略
}
.barMode(BarMode.Scrollable)// 滚动
// .barMode(BarMode.Fixed)// 默认值

容器组件 Tabs – 自定义TabBar – 基础结构

TabBar 在底部,一般会显示 图形 文字甚至有 特殊的图标

Tabs() {
  TabContent() {
  // 内容略
 }
 .tabBar(this.tabBarBuilder())
}
@Builder
tabBarBuilder() {
  // 自定义的Tabbar结构
}

容器组件 Tabs – 自定义TabBar – 高亮切换

核心思路:

1. 监听切换事件 → 得到索引值,记录高亮的索引

2. 给每个 tabBar起个标记,0,1,2

3. 在 tabBar 内部比较 标记 == 记录的索引 ? 高亮 : 不高亮

自定义组件 - 基础

自定义组件 - 基本使用

概念:由框架直接提供的称为 系统组件,由开发者定义的称为 自定义组件

@Entry
@Component
struct Index {
  build() {
  Column() {
   Text('系统组件')
   // 自定义组件
   HelloComponent()
   HelloComponent()
  }
 }
}


// 定义
@Component
struct HelloComponent {
 // 状态变量
 @State message:string =''
  build(){
 // .... 描述 UI
 }
}

自定义组件 - 通用样式事件

自定义组件可以通过点语法,设置 通用样式, 通用事件

如果想要单独预览组件,可以使用 @Preview 进行装饰

@Entry
@Component
struct Index {
  build() {
   Column() {
    HelloComponent()
    .width(200)
    .height(100)
    .backgroundColor(Color.Orange)
   .onClick(() => {
     console.log('外部添加的点击事件')
   })
  }
 }
}
@Preview
@Component
export struct HelloComponent {
 @State info: string = '默认info'
 build() {
  Row() {
   Text(this.info)
   Button('修改数据')
  }
 }
}

自定义组件 – 成员函数变量

除了必须要实现 build() 函数外,还可以定义其他的成员函数,以及成员变量。

成员变量的值 → 外部可传参覆盖

@Component
struct HelloComponent {
 // 状态变量
 @State msg:string = ''
  // 成员变量-数据
  info:string = ''
  // 成员变量-函数
  sayHello = () => {}
  // 成员函数
  sayHi(){}
   build(){
   // .... 描述 UI
 }
}
@Entry
@Component
struct CustomComponentDemo {
 build() {
  Column() {
  // 使用组件内部定义的初始值
  HelloComponent()
  // 使用传入的值,覆盖子组件的默认值
  HelloComponent({ info: '你好', msg: 'ArkTS' })
  // 函数也可以传入
  HelloComponent({ sayHello(){ console.log('传入的逻辑') } })
  }
 }
}

@BuilderParam 传递UI

利用 @BuilderParam 构建函数,可以让自定义组件 允许外部传递 UI。

@Entry
@Component
struct Index {
  build() {
    Column({ space: 15 }) {
    SonCom() {
 // 直接传递进来(尾随闭包)
     Button('待付款')
     }
   }
  }
}
@Component
struct SonCom {
  // 1.定义 BuilderParam 接受外部传入的 ui, 并设置默认值
  @BuilderParam ContentBuilder: () => void = this.defaultBuilder
  // 默认 的 Builder 
  @Builder
defaultBuilder() {
  Text('默认的内容')
}
build() {
  Column() {
// 2. 使用 @BuilderParam 装饰的成员变量
  this.ContentBuilder()
  }
 }
}

多个 @BuilderParam 参数

子组件有多个BuilderParam,必须通过参数的方式来传入

@Component
struct SonCom {
 // 由外部传入 UI
 @BuilderParam tBuilder: () => void = this.tDefaultBuilder
 @BuilderParam cBuilder: () => void = this.cDefaultBuilder
 // 设置默认 Builder
 @Builder
 tDefaultBuilder() { ... }
 @Builder
 cDefaultBuilder() { ... }
 build() {
  Column() {
   this.tBuilder()
   this.cBuilder()
  }
 }
}
@Entry
@Component
struct Index {
@Builder
fTBuilder() { ... }
@Builder
fCBuilder() { ... }
  build() {
   Column({ space: 15 }) {
     SonCom({ 
       tBuilder: this.fTBuilder, 
       cBuilder: this.fCBuilder
      })
   }
 }
}

布局

线性布局

线性布局(LinearLayout)通过线性容器 Column Row 创建。

Column 容器:子元素 垂直方向 排列

Row 容器:子元素 水平方向 排列

排布主方向上的对齐方式 (主轴)

属性:.justifyContent(枚举FlexAlign) (Row 组件的 justifyContent 属性效果相似)

交叉轴对齐方式

属性:alignItems()

参数:枚举类型

交叉轴在水平方向:HorizontalAlign

交叉轴在垂直方向:VerticalAlign

交叉轴对齐方式:

alignItems()

自适应伸缩

设置 layoutWeight 属性的 子元素 与 兄弟元素,会 按照权重 进行分配 主轴 空间 (剩余空间)

语法:.layoutWeight(数字)

Row() {
  Text('左侧')
    .layoutWeight(1)
    .height(50)
    .backgroundColor(Color.Pink)
  Text('右侧')
    .width(70)
    .height(50)
    .backgroundColor(Color.Orange)
}

弹性布局(Flex)

参数对象:

1. 主轴方向:direction

2. 主轴对齐方式:justifyContent

3. 交叉轴对齐方式:alignItems

4. 布局换行:wrap

单行或者单列: 优先使用线性布局(基于Flex设计,做了性能优化)

wrap 属性:换行

1. FlexWrap.NoWrap 单行布局

2. FlexWrap.Wrap 多行布局

Flex({ 
 wrap: FlexWrap.Wrap
})

绝对定位

作用:控制组件位置,可以实现层叠效果

特点:

1. 参照 父组件左上角 进行偏移

2. 绝对定位后的组件 不再占用自身原有位置

语法:.position(位置对象)

参数:{ x: 水平偏移量, y: 垂直偏移量 }

Text('文字内容')
.position({
  x: 0,
  y: 0
})

zIndex 层级

作用:调整组件层级

语法:.zIndex(数字)

参数:取值为整数数字,取值越大,显示层级越高

层叠布局

层叠布局

层叠布局具有较强的组件层叠能力。场景:卡片层叠效果

特点:层叠操作更简洁编码效率高。(绝对定位的优势是更灵活

Stack 容器内的⼦元素的顺序为 Item1 -> Item2 -> Item3

Stack() {
  Item1()
  Item2()
  Item3()
}

特点:层叠操作更简洁编码效率高。(绝对定位的优势是更灵活

Grid 布局

GridItem() {
  Badge({
    count: 1,
    position: BadgePosition.RightTop,
    style: {
      fontSize: 14,
      badgeSize: 20,
      badgeColor: '#fa2a2d'
  }
}) {
   Image($r('app.media.bg_01'))
      .width(80)
  }
}

交互

点击事件

交互 – 点击事件

说明:组件 被点击时 触发的事件

作用:监听(感知)用户 点击行为,进行对应操作

语法:onClick( (参数) => {} )

Button('点我, 显示弹框')
  .onClick(() => {
     AlertDialog.show({
     message: '你好-这是个弹框'
  })
})

状态管理

之前构建的页面多为静态界面。

但如果希望构建一个动态的有交互的界面,就需要引入“状态”的概念

点击交互 触发了 文本状态变更状态变更 引起了 UI渲染

普通变量:只能在初始化时渲染,后续将不会再刷新。

let msg1: string = 程序员'
@Entry
@Component
struct Index {
  msg2: string = '学鸿蒙'
  build() {
    Column() {
      Text(msg1)
      Text(this.msg2)
     }
  }
}

状态变量:需要装饰器装饰改变会引起 UI 的渲染刷新 (必须设置 类型 初始值

@Entry
@Component
struct Index {
  @State msg3: string = 'Hello World'
  build() {
    Column() {
      Text(this.msg3).onClick(() => {
        this.msg3 = '你好, 世界'
      })
    }
  }
}

注意:定义在 组件内 普通变量 或 状态变量,都需要 通过 this 访问

@State 自己的状态

注意:不是状态变量的所有更改都会引起刷新。只有可以被框架观察到的修改才会引起UI刷新。

1. boolean、string、number类型时,可以观察到数值的变化

2. class或者Object时,可观察 自身的赋值 的变化, 第一层属性赋值的变化,Object.keys(observedObject) 返回的属性。

// 状态变量
@State message: string = 'Hello, World!';
@State person: Person = {
  name: 'jack',
  dog: {
  name: '柯基'
  }
}

Button('修改title外层属性')
  .onClick(() => {
    this.person.name = '666'
})
Button('修改title嵌套属性')
  .onClick(() => {
  // 无法触发更新
  // this.person.dog.name = '内部的 666' 
  this.person.dog = {
   name: '阿拉斯加'
  }
})

@Prop - 父子单向

@Prop 装饰的变量可以和父组件建立单向的同步关系。

@Prop 装饰的变量是可变的,但是变化不会同步回其父组件

@Entry
@Component
struct FatherCom {
  @State info: string = '么么哒'
  build() {
    Column() {
    Text(this.info)
    SonCom({
        info: this.info,
        changeInfo: (newInfo: string) => {
        this.info = newInfo
        }
     })
   }
 }
}

@Component
struct SonCom {
@Prop info: string
  changeInfo = (newInfo: string) => {
}
build() {
  Button('info:' + this.info)
    .onClick(() => {
      this.changeInfo('改啦')
    })
  }
}

使用 @Link 可以实现父组件和子组件的 双向同步:

使用步骤:

1. 将父组件的状态属性传递给子组件

2. 子组件通过@Link修饰即可

3. 分别测试基础,和复杂类型

@Provide、@Consume后代组件

将数据传递给后代,和后代的数据进行双向同步

使用步骤:

1. 将父组件的状态属性使用 @Provide 修饰

2. 子组件通过 @Consume 修饰

3. 分别测试 基础 复杂 类型

说明:装饰器仅能观察到 第一层 的变化。对于多层嵌套的情况,比如 对象数组 等。

他们的第二层的属性变化是无法观察到的。这就引出了@Observed/@ObjectLink装饰器

作用:用于在 涉及嵌套对象 或 数组 的场景中进行 双向数据同步

注意:ObjectLink修饰符不能用在 Entry 修饰的组件中

路由

页面路由指的是在应用程序中实现 不同页面之间的跳转,以及数据传递。

路由 – 1. 创建页面

① 直接右键新建Page

② 新建普通ets文件,配置成页面

新建普通页面 pages/DetailPage.ets

文件位置 → main_pages.json

路由 – 2. 页面跳转 和 后退

// 导入
import router from '@ohos.router';
// 1.调用方法 - 普通跳转(可以返回)
router.pushUrl({
  url:'页面地址'
})
// 2.调用方法 - 替换跳转(无法返回)
router.replaceUrl({
  url:'页面地址'
})
// 3.调用方法 - 返回()
router.back()

路由 – 3. 页面栈

页面栈是用来存储程序运行时页面的一种 数据结构,遵循 先进后出 的原则

页面栈的最大容量为 32 个页面

// 获取页面栈长度

router.getLength()

// 清空页面栈

router.clear()

路由 – 4. 路由模式

路由提供了两种不同的跳转模式

1. Standard:无论之前是否添加过,一直添加到页面栈【默认常用】

2. Single:如果目标页面已存在,会将已有的最近同url页面移到栈顶【看情况使用】

// 在第二个参数设置 【路由模式】

router.pushUrl(options, mode)

路由 – 5. 路由传参

日常开发中有这样的场景:点击不同的电影,商品,标题等,需要跳转到与之对应的详情页面

router.pushUrl({
url:'地址',
 params:{
  // 以对象的形式传递参数
 }
})

// -------------页面 B接收并解析参数------------
aboutToAppear(): void {
// 1.确认内容
 console.log(JSON.stringify(router.getParams()))
// 2.通过 as 类型断言 转为具体的类型
 const params = router.getParams() as 类型
 // 3. 通过点语法即可取值
 params.xxx
}

ForEach-渲染控制

ForEach 可以基于数组的个数,渲染组件的个数。(简化代码)

语法: ForEach(arr, (item, index) => {})

@State titles:string[] = ['电子产品', '精品服饰', '母婴产品', 
'影音娱乐', '海外旅游']
build() {
  Column() {
    ForEach(this.titles, (item: string, index) => {
 Text(item)
   .fontSize('24')
   .fontWeight(700)
   .fontColor(Color.Orange)
   .width('100%')
   .padding(15)
  })
 }
}

生命周期

组件 页面 在创建、显示、销毁的这一整个过程中,会自动执行 一系列的【生命周期钩子】

其实就是一系列的【函数】,让开发者有机会在特定的阶段运行自己的代码

区分 页面 和 组件:@Entry

aboutToAppear:创建组件实例后执行,可以修改状态变量

aboutToDisappear:组件实例销毁前执行,不允许修改状态变量

onPageShow:页面每次显示触发(路由过程、应用进入前后台)

onPageHide:页面每次隐藏触发(路由过程、应用进入前后台)

onBackPress:点击返回触发(return true 阻止返回键默认返回效果)

仅@Entry修饰的页面组件生效

Stage模型

应用模型 是系统为开发者提供的应用程序所需能力的抽象提炼,它提供了应用程序必备的组件和运行机制

简而言之:应用模型就是 应用的施工图纸, 他规范化了: 程序运行流程、项目结构、文件功能等...

了解应用模型之后,就可以知道:

1. 实现某个功能需要在哪个文件编码

2. 如何感知应用的 状态变化(启动、关闭、切后台)

3. 如何调整项目配置

...

随着系统的演进发展,先后提供了两种应用模型:

1. FA 模型:从API 7开始支持的模型,已经 不再主推

2. Stage 模型:从API 9开始新增的模型,是目前 主推且会长期演进的模型

ArkTS 中每个 ets 文件,都可以看做是一个模块

AppScope > app.json5:应用的全局配置信息。

• entry:HarmonyOS工程模块,编译构建生成一个HAP包。

• src > main > ets:用于存放ArkTS源码。

• src > main > ets > entryability:应用/服务的入口。

• src > main > ets > pages:应用/服务包含的页面。

• src > main > resources:用于存放应用/服务所用到的资源文件。

• src > ain > module.json5:模块应用配置文件。

• build-profile.json5:当前的模块信息 、编译信息配置项,包括buildOption、targets配置等。

• hvigorfile.ts:模块级编译构建任务脚本,开发者可以自定义相关任务和代码实现。

• obfuscation-rules.txt:混淆规则文件。。

• oh_modules:用于存放三方库依赖信息。

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

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

Stage模型 – app.json5 应用配置

应用配置在工程的 AppScope 目录下的 app.json5 配置文件中

{
 "app": {
 "bundleName": "包名 不可省略",
 "vendor": "应用开发厂商描述 不可省略",
 "versionCode": 版本号,数值越大版本越高,
 "versionName": "给用户看的版本号",
 "icon": "应用图标",
 "label": "应用名"
 }
}

Stage模型 – module.json5 模块配置

module.json5 配置文件,配置 ability 入口图标 和 标签配置

{
 "module": {
 ...
 "abilities": [
 {
"icon": "$media:icon",
"label": "$string:EntryAbility_label",
 }
 ...
 ]
 }
}

Stage模型 - UIAbility 组件

每一个UIAbility实例,都对应于一个最近任务列表中的任务。

UIAbility是一种包含用户界面的应用组件,主要用于和用户进行交互

一个应用可以有一个 UIAbility 也可以有多个 UIAbility

单 UIAbility:任务列表只有一个任务。

多 UIAbility:在任务列表中会有多个任务。

相关知识点:

UIAbilitiy 配置启动页面

UIAbilitiy 生命周期

UIAbilitiy 组件间交互

Stage模型 - UIAbility 组件的生命周期

当用户打开、切换和返回到对应应用时,应用中的UIAbility实例会在其生命周期的不同状态之间转换。

onCreate: Ability创建时回调,执行初始化业务逻辑操作。

onDestory: Ability销毁时回调,执行资源清理等操作。

onForeground: 当应用从后台转到前台时触发。

onBackground: 当应用从前台转到后台时触发

模块化语法

模块化基本认知

模块化:把一个大的程序,【拆分】成若干的小的模块,通过【特定的语法】,可以进行任意组合

默认导出和导入

默认导出:指一个模块,只能默认导出的 一个值 或 对象。使用时,可以 自定义 导入名称。

使用步骤:

1. 当前模块中 导出模块

2. 需要使用的地方 导入模块

// 默认导出
export default 需要导出的内容
// 默认导入
import xxx from '模块路径'

按需导出和导入

按需导出:指一个模块,可以按照需要,导出多个特性

// 逐个导出单个特性
export let name1 = …, name2 = …, …, nameN; 
export function FunctionName(){...}
export class ClassName {...}
// 一次性导出
export { name1, name2, …, nameN };
// --------------------------------
// 导入
import { name1, name2, name3 as 别名 } from "module-name";

全部导入

将所有的按需导入,全部导入进来 → 导出部分不需要调整,调整导入的语法即可

import * as Utils from './utils'
// 通过 Utils 即可获取 utils模块中导出的所有内容