为有牺牲多壮志,敢教日月换新天。

ArkTS:声明式UI语法

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤博客园地址:为敢技术(https://www.cnblogs.com/strengthen/ 
➤GitHub地址:https://github.com/strengthen
➤原文地址:https://www.cnblogs.com/strengthen/p/18471722
➤如果链接不是为敢技术的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

一、什么是声明式UI
1、声明式UI具有两大特征:
(1)、声明式描述:开发时只需要去描述UI应该呈现的结果,而不用关心内部如何实现。
(2)、状态驱动视图更新:开发过程中不会直接去操作UI,而是通过操作状态数据,来间接地改变UI内容。

声明式描述,举例:看到的界面是什么样子的,在代码中就进行什么样的描述,过程则交由框架去实现。

状态驱动视图更新,举例: 在ArkTS中,状态是驱动应用变化的数据,视图则是与状态相关联的UI内容,当状态改变时,框架会自动更新与状态相关联的视图,实现内容的动态更新。

状态驱动视图更新,代码实现:首先,这个操作是使用装饰器@State,使变量isComplete成为状态变量。并且在UI描述时使用这个状态变量,建立起状态数据与视图间的依赖关系。当用户点击的时候,在点击事件里面,改变isComplete的状态,ArkUI感知到了状态变化后,会直接触发视图的更新,这就是声明式的第二特征:状态驱动视图更新。

import CommonConstants from '../common/constant/CommonConstant';

@Component
export default struct ToDoItem {
  private content?: string;
  @State isComplete: boolean = false;

  @Builder labelIcon(icon: Resource) {
    Image(icon)
      .objectFit(ImageFit.Contain)
      .width($r('app.float.checkbox_width'))
      .height($r('app.float.checkbox_width'))
      .margin($r('app.float.checkbox_margin'))
  }

  build() {
    Row() {
      if (this.isComplete) {
        this.labelIcon($r('app.media.ic_ok'));
      } else {
        this.labelIcon($r('app.media.ic_default'));
      }

      Text(this.content)
        .fontSize($r('app.float.item_font_size'))
        .fontWeight(CommonConstants.FONT_WEIGHT)
        .opacity(this.isComplete ? CommonConstants.OPACITY_COMPLETED : CommonConstants.OPACITY_DEFAULT)
        .decoration({ type: this.isComplete ? TextDecorationType.LineThrough : TextDecorationType.None })
    }
    .borderRadius(CommonConstants.BORDER_RADIUS)
    .backgroundColor($r('app.color.start_window_background'))
    .width(CommonConstants.LIST_DEFAULT_WIDTH)
    .height($r('app.float.list_item_height'))
    .onClick(() => {
      this.isComplete = !this.isComplete;
    })
  }
}
二、创建自定义组件
应用的UI界面都是由页面组成,使用ArkTS开发页面,就是通过声明式开发范式,创建和组合自定义组件的过程。
自定义组件式通过组合基础组件,封装得到可重用,可组合的UI单元。

@Entry装饰器的作用,表示这是一个入口页面,可以通过UIAbility进行加载,

声明了自定义组件后,还需要UI描述才能够展示内容。需要在struct结构体内,配置build函数,build函数是自定义组件进行声明式UI描述的地方。build函数采用花括号,包裹要描述的UI,UI描述中采用大括号和缩进,来区分组件,以及内部的内容。

在这个ToDoListPage自定义组件内,包含了有作为容器的Column,Column内部包含了用于显示文字的Text组件,以及封装的自定义组件ToDoItem。通过对页面内容进行合理抽象,提取结构相同以及功能明确的UI单元,组合为自定义组件,并且对自定义组件进行合理组合,就能够完成应用页面的搭建。

三、配置属性与布局
有时候组件的样式并不是我们想要的结果,为了让页面达到预期的展示效果,常常需要对组件进行样式和布局的调整。
ArkTS支持以点运算符的方式,给内置组件配置属性,可以通过点运算符设置待办字体大小。

ToDoItem是一个圆圈和一个文字在横向排列,这里涉及到两个组件间的排列关系,就需要布局来组织这种多个组件之间的排列关系。

布局:多个组件的排列关系。

容器组件:描述多个组件间布局关系的组件。

使用方式是采用花括号语法,来包括想要组织的内容。相应的内容在其中按照顺序进行排列。

Row容器是一种行排列容器,在其中的组件会按照横向排列。

定义一个content的属性,来保存传入的内容,然后通过Text组件,展示content内容,在使用该组件时,对花括号中content传入相应的内容,就可以创建对应内容的ToDo Item组件。

Column是一种列布局容器,在其中的组件会按照纵向排列。

1、通过调整代办标题的样式,熟悉了如何对组件进行属性的配置。

2、自定义组件的封装。

3、使用容器描述布局。

四、改变组件状态

通过ArkTS提供的装饰器@State,来装饰isComplete,从而让视图和状态之间建立绑定关系, 

像这种控制页面内容消失和生成,可以使用if/else条件渲染语句。在if和else分支中,分别根据条件condition的不同,来展示不同的内容。

对于文字部分,为了更好的突出已完成状态,可以让文字更淡一些,并加一个删除线,来更好的让用户知道任务已完成。

使用opacity来控制不透明度。使用decoration属性,控制是否加删除线。

在Row容器上配置点击事件onClick,在事件内修改isComplete的值,就能够实现点击待办项,从而改变待办项显示的内容了。

五、渲染列表数据

列表可以有很多的列表项,如何完成多个列表项的构建?通过ForEach语法可以快速创建相应的UI内容。

ForEach需要接受的两个参数:

第一个参数是:数据源,

第二个参数是:生成器函数,函数的参数item,对应于数组的每一项内容,并在函数体内可以生成相应的页面布局content。

因为我们要实现的是对每一项数据,都生成一个待办项,所以要生成的内容,也就是ToDoItem自定义组件,

在ToDoListPage页面内,使用ForEach语法,就可以快速把数组内的数据渲染到页面上。

import DataModel from '../viewmodel/DataModel';
import CommonConstants from '../common/constant/CommonConstant';
import ToDoItem from '../view/ToDoItem';

@Entry
@Component
struct ToDoListPage {
  private totalTasks: Array<string> = [];

  aboutToAppear() {
    this.totalTasks = DataModel.getData();
  }

  build() {
    Column({ space: CommonConstants.COLUMN_SPACE }) {
      Text($r('app.string.page_title'))
        .fontSize($r('app.float.title_font_size'))
        .fontWeight(FontWeight.Bold)
        .lineHeight($r('app.float.title_font_height'))
        .width(CommonConstants.TITLE_WIDTH)
        .margin({
          top: $r('app.float.title_margin_top'),
          bottom: $r('app.float.title_margin_bottom')
        })
        .textAlign(TextAlign.Start)

      ForEach(this.totalTasks, (item: string) => {
        ToDoItem({ content: item })
      }, (item: string) => JSON.stringify(item))
    }
    .width(CommonConstants.FULL_LENGTH)
    .height(CommonConstants.FULL_LENGTH)
    .backgroundColor($r('app.color.page_background'))
  }
}

posted @ 2024-10-17 11:38  为敢技术  阅读(121)  评论(0编辑  收藏  举报