随着HarmonyOS 3.0 Beta版的公布,API Version 8新增了少量JS/eTS API接口,置信很多开发者曾经急不可待想体验基于eTS的HamronyOS利用开发。本期Codelab,咱们将基于API Version 8实现一个HarmonyOS课程类利用,帮忙大家学习eTS的申明式UI形容、循环渲染、状态数据管理等机制,体验基于eTS的极简高效开发。

一、整体介绍

在课程类利用界面中,左侧为课程分类导航栏,右侧为各个类别的课程内容。当用户高低滑动右侧课程内容时,左侧导航栏会跳转至对应的课程分类。当用户点击左侧导航栏的课程分类时,会高亮显示点击的内容,且右侧课程内容会跳转至对应类别的课程列表。
那么如何基于eTS高效实现这样一个HarmonyOS课程类利用?上面咱们将从申明式UI形容、循环渲染数据、状态数据管理三个维度来解析。
1. 申明式UI形容
界面布局是UI界面的骨架,决定了利用界面的交互和视觉格调。本示例中咱们将通过eTS的一系列根底组件以申明式形式进行组合和扩大,并采纳靠近天然语义的编程语法直观地形容UI界面,包含参数结构配置、属性配置、事件配置以及子组件配置等。
相较于基于Java的命令式开发,eTS采纳更靠近天然语义的申明式编程语法,让开发者能够更直观地形容UI界面,无效地升高了开发者的上手老本,极大水平地晋升了UI界面的构建效率,实现极简高效开发。
2. 循环渲染数据
数据模型是UI界面的精神,形容了界面中数据的动态特色、动静行为和约束条件。本示例中咱们将通过eTS直观地定义界面中各个模块的数据模型,蕴含名称、标识、图片链接等,并依据数据模型写入对应的数据。最初应用eTS提供的循环渲染机制(ForEach)将写入的数据循环渲染至对应的界面中。
相较于基于Java的命令式开发,eTS在渲染数据时UI的更新不须要开发者应用代码被动刷新,而是交给框架层主动解决,开发者不用关怀框架如何实现UI绘制和渲染,实现界面数据的高效渲染。
3. 状态数据管理
联动成果是UI界面的灵魂,实现了界面中布局与数据的动静交互,本示例中咱们将应用eTS提供的状态数据管理机制通过装璜组件领有的状态属性,当装璜的变量更改时,组件会从新渲染更新UI界面数据,从而实现联动成果。
相较于基于Java的命令式开发,eTS通过性能不同的装璜器给开发者提供了清晰的页面更新渲染流程和管道。开发者要做的就是定义数据与UI的映射关系,前面只须要通过状态装璜器监听数据的状态,UI即可主动刷新,这极大地加重了程序员对UI的保护工作。
以上就是实现课程类利用的外围原理,上面咱们将为大家带来各局部的具体实现。

二、搭建界面布局

eTS提供了多种布局形式,不仅保留了经典的弹性布局能力,也提供了列表、宫格、栅格布局和适应多分辨率场景开发的原子布局能力。如图1所示,本示例中整体布局应用Row沿程度方向布局容器,并设置背景色彩为红色,Row外部嵌套Scroll及List容器别离作为利用界面的导航栏布局和课程内容布局,上面咱们将为你一一道来。

                                   图1 整体布局

1. 导航栏布局
利用界面的导航栏应用可滚动的容器组件Scroll来实现,Scroll内嵌Text组件用于显示“课程分类”名称,如图2所示:

                                  图2 导航栏布局

Scroll容器必须内置一个子组件,咱们应用了垂直方向的布局容器Column,并设置填充高度为height('100%')。“课程分类”名称应用Text组件实现,并设置文字色彩为fontColor(0x696969)、文字大小为fontSize(16)、文字对齐形式为textAlign(TextAlign.Center)居中显示、高度为height(60)、宽度为width('100%')。
相干代码如下:

Scroll() {  Column() {    ForEach(this.tabArray.map((item1, index1) => {      return { index: index1, data: item1 };    }), item => {      Text(item.data.superName)        .fontColor(0x696969)        .backgroundColor(this.index == item.index ? 0xffffff : null)        .fontSize(16)        .width('100%')        .height(60)        .textAlign(TextAlign.Center)        .onClick(() => {          if (this.index != item.index) {            this.index = item.index            this.scroller.scrollToIndex(item.data.position)          }        })    }, item => '' + item.data)  }.height('100%')}.width(100).height('100%').backgroundColor(0xdddddd).scrollBar(BarState.Off)

2. 课程内容布局
利用的课程内容局部的布局应用List列表容器来实现,并应用ForEach循环渲染listArray(课程内容)数据,如图3所示,课程内容布局蕴含头部和课程信息两局部(头部和右边的导航栏对应),上面咱们将别离介绍头部及课程信息的布局的实现。

                                 图3 课程内容布局

(1) 头部布局
头部应用Text组件实现,并设置了文字色彩为fontColor(0x696969)、文字大小为fontSize(20)、高度为height(40)、宽度为width('100%')填充、内边距为padding({ left: 10 })、背景色彩为backgroundColor(0xefefef)。同时,头部的ListItem设置了sticky(Sticky.Normal)属性,使其滑动到顶部时能够出现固定的成果。代码如下:

if (item.tag) {  ListItem() {    Text(item.courseName)      .fontColor(0x696969)      .fontSize(20)      .height(40)      .width('100%')      .padding({ left: 10 })      .backgroundColor(0xefefef)  }.sticky(Sticky.Normal)

(2) 课程信息布局
课程信息局部应用Stack重叠容器,高度设置为height(120),设置子组件在容器内的对齐形式为Alignment.TopStart。Stack组件内嵌Image、Text、Divider组件,用于出现课程图片、课程题目、课程价格及分割线等信息。具体如下:
●课程的图片应用Image组件出现,设置宽度为width(130),高度为height(100),图片的缩放类型为objectFit(ImageFit.Fill),使图片填充斥组件,并设置右边、顶部边距均10,使其组件居中对齐。代码如下:

Image(item.imageUrl)  .objectFit(ImageFit.Cover)  .width(130)  .height(100)  .margin({ left: 10, top: 10 })

●课程名称应用Text组件,设置文字色彩为fontColor(0x363636)、文字大小为fontSize(14),最大显示行数为maxLines(2)两行,文本超长时的显示方式为TextOverflow.Clip,意为进行裁剪显示。代码如下:

Text(item.courseName)  .fontColor(0x363636)  .fontSize(14)  .margin({ left: 150, top: 12 })  .maxLines(2)  .textOverflow({ overflow: TextOverflow.Clip })

●课程的价格应用Text组件,设置文字色彩为fontColor(0xff6600)、文字大小为fontSize(24),并应用了相对定位position({ x: 0, y: '100%' })先让组件显示在Stack容器最底部的外边界下,而后应用锚点定位markAnchor({ x: 0, y: '100%' })使组件以本身高度向上偏移,让组件显示在Stack容器最底部。代码如下:

Text(item.price == 0 ? '收费' : '¥' + item.price)  .fontColor(0xff6600)  .fontSize(24)  .position({ x: 0, y: '100%' })  .markAnchor({ x: 0, y: '100%' })  .margin({ bottom: 18, left: 150 })

●分割线应用Divider组件实现,并设置了分割线色彩为color(0xefefef)、分割线宽度为strokeWidth(0.7)、左右边距margin({ left: 10, right: 10 })均为10,并应用相对定位position({ x: 0, y: '100%' })和锚点定位markAnchor({ x: 0, y: '100%' })使分割线出现在Stack容器最底部。代码如下:

Divider()  .margin({ left: 10, right: 10 })  .color(0xefefef)  .strokeWidth(0.7)  .position({ x: 0, y: '100%' })  .markAnchor({ x: 0, y: '100%' })

至此,咱们曾经实现了界面布局,此时界面只是一个没有任何内容的骨架。接下来咱们将为利用界面增加数据模型。

三、构建数据模型

本章节咱们将为大家介绍本示例中数据模型的定义、数据的预置以及数据的加载。
1. 定义数据模型
本示例需定义两个数据模型,别离是利用界面中左侧导航栏的“课程分类”和右侧的“课程内容”。其中:
● 导航栏“课程分类”定义了名称(superName)和地位(position)属性。数据模型定义如下:

export class TabItem {  position: number; // 点击该分类时课程内容滑动到的地位  superName: string; // 课程分类题目  constructor(position: number, superName: string) {    this.position = position;    this.superName = superName;  }}

● “课程内容”定义了课程的名称(courseName)、课程的图片地址(imageUrl)、课程的价格(price)、判断是否为此类别课程头部的变量(tag)、课程所对应课程类别的索引地位(index),数据模型定义如下:

export class CourseItem {  tag: boolean; // 是否此类别课程的头部  index: number; // 课程所对应课程类别的索引地位  courseName: string; // 课程名称  imageUrl: string; // 图片地址  price: number; // 价格  constructor(tag: boolean, index: number, courseName: string, imageUrl: string, price: number) {    this.tag = tag;    this.index = index;    this.courseName = courseName;    this.imageUrl = imageUrl;    this.price = price;  }}

2. 预置数据
在entry/src/main/ets/MainAbility/Model.ets文件中,放入筹备好的模仿数据,其中,superId是课程分类的惟一标识、id是课程内容的惟一标识。格局如下:

const LinkData: any[] = [  {     "superId": 1,     "superName": "热门课程",     "id": 1,     "courseName": "利用市场介绍",     "imageUrl": "/image/image1.jpg",     "price": 0   }, {    "superId": 1,    "superName": "热门课程",    "id": 2,    "courseName": "上架流程",    "imageUrl": "/image/image2.jpg",    "price": 100  },  ... ]

3. 加载数据更新UI
本章节将介绍如何加载本地结构的模仿数据并出现到界面。
(1) 加载数据
在index.ets文件中,通过getLinkData()获取预置数据。

aboutToAppear() {  // 延时数据加载  setTimeout(() => {    let linkDataItem = getLinkData();    this.tabArray = linkDataItem.tabArray;    this.listArray = linkDataItem.listArray;    this.requestSuccess = true;  }, 2000)}

(2) 渲染
● 导航栏应用ForEach循环渲染tabArray(课程分类)数据。这里的ForEach的第一个参数须要应用数组的map()办法遍历。代码如下:

let superId: number = 0model.forEach((item) => {  if (superId != item.superId) {    let tabItem = new TabItem(this.listArray.length, item.superName);    this.tabArray.push(tabItem)    let courseItem = new CourseItem(true, this.tabArray.length - 1, item.superName, '', 0);    this.listArray.push(courseItem)  }})

● 课程内容应用ForEach循环渲染listArray(课程内容)数据。代码如下:

ForEach(this.listArray, item => {  if (item.tag) {    ListItem() {    ......    }.sticky(Sticky.Normal)  } else {    ListItem() {      Stack({ alignContent: Alignment.TopStart }) {      ......      }.height(120)    }  }}, item => '' + item)

通过上文的介绍,咱们曾经实现了利用界面的布局以及界面数据的出现,此时界面就像没有灵魂的躯壳。上面咱们将为大家介绍利用中联动成果的实现。

四、实现界面联动

本示例中的联动成果包含导航栏高亮显示、滑动课程内容对应导航栏变动、点击导航栏课程分类跳转到对应课程内容,上面咱们将一一道来。

1. 导航栏高亮显示
实现导航栏高亮显示,次要通过@State装璜器监听导航栏课程分类的索引值的状态变动,当用户滑动课程内容或点击导航栏,对应课程分类的索引值发生变化,此时将调用build办法进行UI刷新,从而实现导航栏背景色的批改。相干代码如下:

@State index: number= 0; // 导航栏课程分类的索引Text(item.data.superName)  .backgroundColor(this.index == item.index ? 0xffffff : null)

2. 左边滑动,右边变动
滑动左边课程内容,对应右边导航栏变动,次要通过onScrollIndex()事件来判断以后课程内容所属的课程分类,当用户滑动课程内容时,对应课程内容的索引值发生变化,导航栏的课程分类的索引值也随之变动。相干代码如下:

private scroller: Scroller = new Scroller()List({ scroller: this.scroller }) {  ......  }.onScrollIndex((firstIndex: number) => {  if (this.index != this.listArray[firstIndex].index) {    this.index = this.listArray[firstIndex].index  }})

3. 右边点击,左边跳转
点击右边导航栏跳转到对应课程内容,次要通过onClick()事件监听用户点击,当用户点击导航栏,scrollToIndex()办法会依据点击的导航栏课程分类的索引值跳转到对应的课程内容界面。相干代码如下:

Text(item.data.superName)  .onClick(() => {    if (this.index != item.index) {      this.index = item.index      this.scroller.scrollToIndex(item.data.position)    }  })

以上就是本期全部内容,通过本期Codelab的学习,置信你曾经把握了eTS的申明式UI形容、循环渲染、状态数据管理等机制,赶快趁热打铁,开发更多乏味的利用吧!