鸿蒙基础之ArkUI简介、布局、组件、组件通讯方式等基础概念

278 阅读8分钟
  • UI:  即用户界面
  • 组件:  UI构建与显示的最小单位,如列表、网格、按钮、单选框、进度条、文本等。开发者通过多种组件的组合,构建出满足自身应用诉求的完整界面。

开发范式

分别是基于ArkTS的声明式开发范式(简称“声明式开发范式”)和兼容JS的类Web开发范式(简称“类Web开发范式”)这里只介绍推荐的性能更佳的 ArkTS的声明式开发范式其他的自行了解。。。

组件

组件是UI的必要元素,形成了在界面中的样子,由框架直接提供的称为系统组件,由开发者定义的称为自定义组件。组件可以自由组合、复用(封装)、便于维护。

架构

image.png

布局方案

  • 确定页面的布局结构。
  • 分析页面中的元素构成。
  • 选用适合的布局容器组件或属性控制页面中各个元素的位置和大小。

布局方案.png

显示图片 (Image)

开发者经常需要在应用中显示一些图片,例如:按钮中的icon、网络图片、本地图片等,Image支持多种图片格式,包括png、jpg、bmp、svg、gif和heif,具体用法请参考Image组件

Image支持加载存档图、多媒体像素图两种类型

  • 存档图类型数据源:存档图类型的数据源可以分为本地资源【创建文件夹,将本地图片放入ets文件夹下的任意位置。Image组件引入本地图片路径,即可显示图片(根目录为ets文件夹)】、网络资源【需申请权限ohos.permission.INTERNET】、Resource资源【使用资源格式可以跨包/跨模块引入图片,resources文件夹下的图片都可以通过$r资源接口读 取到并转换到Resource格式】、媒体库资源【媒体库file://data/storage 支持file://路径前缀的字符串,用于访问通过选择器提供的图片路径】和base64【路径格式为data:image/[png|jpeg|bmp|webp|heif];base64,[base64 data],其中[base64 data]为Base64字符串数据】
  • 多媒体像素图:PixelMap是图片解码后的像素图,具体用法请参考图片开发指导。以下示例将加载的网络图片返回的数据解码成PixelMap格式,再显示在Image组件上

特别的网络图片,需要在module.json5配置文件的requestPermissions标签中声明权限

"requestPermissions": [
  {"name": "ohos.permission.INTERNET"}
],

组件 && Image 使用网络图片

@Entry
@Component
export struct Send {
  @State message: string = '我是第二个页面';

  build() {
    RelativeContainer() {
    // Resource资源模式
    Image($r('app.media.icon'))
   // 网络图片模式 Image('https://cdn.huodongxing.com/file/20170215/1189EA9397FDBCE067A3E0EF4A994ABBFC/30773168495662297.png?auth_key=1536087106-0-0-9519ee335c4df7e9454ca87d3b4e3842')
      Button('返回').width(100).height(100).backgroundColor('#eeeeee').onClick(()=>{
        HMRouterMgr.pop()
      })
    }
    .height('100%')
    .width('100%')
  }
}

Video

通本地视频。加载本地视频时,首先在本地rawfile目录指定对应的文件。

@Component
export struct VideoPlayer{
  private controller:VideoController | undefined;
  private previewUris: Resource = $r ('app.media.preview');
  // 第一种
  private innerResource: Resource = $rawfile('videoTest.mp4');
  // 第二种 [Data Ability](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/dataability-overview-V5)提供的视频路径带有dataability://前缀,使用时确保对应视频资源存在即可。
  private videoSrc: string = 'dataability://device_id/com.domainname.dataability.videodata/video/10'
  // 第三种 网络资源 (需要申请权限ohos.permission.INTERNET)
  private videoSrc: string= 'https://www.example.com/example.mp4' // 使用时请替换为实际视频加载网// 第四种 沙箱路径
  private videoSrc: string = 'file:///data/storage/el2/base/haps/entry/files/show.mp4'
  build(){
    Column() {
      Video({
        src: this.innerResource,
        previewUri: this.previewUris,
        controller: this.controller
      })
    }
  }
}

组件通用信息 参考官方

  • 通用属性
  • 通用事件
  • 手势处理

组件通讯方式

  • 状态管理(V1稳定版)先搞定这个版本的吧
  • 状态管理(V2试用版)(咱先不研究估计后面还是要升级成这个但也许也被阉割)

管理组件拥有的状态

组件化带来的好处包括‌:

  • 提高协作效率‌:组件化可以减少模块间的耦合,使得每个业务模块可以独立存在,互不打扰,降低团队成员熟悉项目的成本,只需关注责任组件‌。
  • 功能重用‌:组件类似于第三方库,只需维护好每个组件,即可在项目中灵活引用和集成‌。
  • 减少重复开发和维护工作量‌:基础组件为新业务提供了基础功能,减少了重复开发的需求‌。

组件化通信的核心是通过协议规则来约束通信,确保业务模块之间的独立性‌。通过解耦各功能模块,使得每个模块可以独立开发和维护,减少了跨业务修改代码的情况,从而提高了系统的稳定性和可维护性‌。

@State

  • @State装饰的变量,与声明式范式中的其他被装饰变量一样,是私有的,只能从组件内部访问,在声明时必须指定其类型和本地初始化
  • @State装饰的变量与子组件中的@Prop装饰变量之间建立单向数据同步,与@Link、@ObjectLink装饰变量之间建立双向数据同步
  • @State装饰的变量生命周期与其所属自定义组件的生命周期相同
  • 不与父组件中任何类型的变量同步
  • 不允许在build里改变状态变量,状态管理框架会在运行时报出Error级别日志
  • 使用a.b(this.object)形式调用,不会触发UI刷新

image.png

@Prop装饰器

  • 父子单向同步,@Prop装饰的变量是可变的,但是变化不会同步回其父组件
  • 当数据源更改时,@Prop装饰的变量都会更新,并且会覆盖本地所有更改。因此,数值的同步是父组件到子组件(所属组件),子组件数值的变化不会同步到父组件
  • @Prop装饰变量时会进行深拷贝,在拷贝的过程中除了基本类型、Map、Set、Date、Array外,都会丢失类型
  • @Prop装饰器不能在@Entry装饰的自定义组件中使用
  • @Prop装饰的变量是私有的,只能在组件内访问
  • @Prop需要被初始化,如果没有进行本地初始化的,则必须通过父组件进行初始化。如果进行了本地初始化,那么是可以不通过父组件进行初始化的。
  • 使用a.b(this.object)形式调用,不会触发UI刷新

image.png

@Link装饰器

  • 父子双向同步
  • @Link装饰的变量与其父组件中的数据源共享相同的值
  • @Link装饰器不能在@Entry装饰的自定义组件中使用
  • 从父组件初始化和更新,必选。与父组件@State, @StorageLink和@Link 建立双向绑定。允许父组件中@State、@Link、@Prop@Provide@Consume@ObjectLink@StorageLink@StorageProp@LocalStorageLink@LocalStorageProp装饰变量初始化子组件@Link
  • @Link装饰的变量和其所属的自定义组件共享生命周期
  • @Link支持联合类型和undefined和null
  • 在子组件中使用@Link装饰状态变量需要保证该变量与数据源类型完全相同,且该数据源需为被诸如@State等装饰器装饰的状态变量
  • 使用a.b(this.object)形式调用,不会触发UI刷新
  • @State放在build后定义时初始化@Link报错(当@State变量放在build函数后定义,用来初始化@Link变量时,会被识别为常量,而@Link变量不能被常量初始化,所以会造成编译报错)

image.png

@Provide装饰器和@Consume装饰器

  • @Provide和@Consume,应用于与后代组件的双向数据同步,应用于状态数据在多个层级之间传递的场景。不同于上文提到的父子组件之间通过命名参数机制传递,@Provide和@Consume摆脱参数传递机制的束缚,实现跨层级传递
  • @Provide装饰的状态变量自动对其所有后代组件可用,即该变量被“provide”给他的后代组件。由此可见,@Provide的方便之处在于,开发者不需要多次在组件之间传递变量
  • 后代通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以在多层级的父子组件之间传递。
  • @Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定,建议类型相同,否则会发生类型隐式转换,从而导致应用行为异常
  • @Provide和@Consume支持联合类型和undefined和null
  • @Provide支持allowOverride参数 allowOverride:@Provide重写选项
  • 和@BuilderParam连用的时候要谨慎this的指向
  • 使用a.b(this.object)形式调用,不会触发UI刷新

image.png

image.png

@Observed装饰器和@ObjectLink装饰器

  • 嵌套类对象属性变化,@State装饰器、@Prop装饰器、@Link装饰器、@Observed装饰器、@ObjectLink装饰器仅能观察到第一层的变化而# @Observed装饰器和@ObjectLink装饰器支持多层嵌套
  • @ObjectLink和@Observed类装饰器用于在涉及嵌套对象或数组的场景中进行双向数据同步
  • @Observed用于嵌套类场景中,观察对象类属性变化,要配合自定义组件使用(示例详见嵌套对象),如果要做数据双/单向同步,需要搭配@ObjectLink或者@Prop使用
  • 使用@Observed装饰class会改变class原始的原型链,@Observed和其他类装饰器装饰同一个class可能会带来问题
  • @ObjectLink装饰器不能在@Entry装饰的自定义组件中使用
  • 必须为被@Observed装饰的class实例,必须指定类型。
  • @Observed装饰class。需要放在class的定义前,使用new创建类对象,@ObjectLink不支持简单类型,可以使用@Prop
  • @ObjectLink装饰的变量不能被赋值,如果要使用赋值操作,请使用@Prop

image.png