0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于eTS的HamronyOS应用开发

HarmonyOS开发者 来源:HarmonyOS开发者 作者:HarmonyOS开发者 2022-07-15 09:20 次阅读

随着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容器分别作为应用界面的导航栏布局和课程内容布局,下面我们将为你一一道来。 7f92ac6e-03db-11ed-ba43-dac502259ad0.png 图1 整体布局

1. 导航栏布局

应用界面的导航栏使用可滚动的容器组件Scroll来实现,Scroll内嵌Text组件用于显示“课程分类”名称,如图2所示: 7fa7daf8-03db-11ed-ba43-dac502259ad0.png

图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所示,课程内容布局包含头部和课程信息两部分(头部和左边的导航栏对应),下面我们将分别介绍头部及课程信息的布局的实现。 7fb1f984-03db-11ed-ba43-dac502259ad0.png

图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)
(左右滑动,查看更多)

通过上文的介绍,我们已经实现了应用界面的布局以及界面数据的呈现,此时界面就像没有灵魂的躯壳。下面我们将为大家介绍应用中联动效果的实现。

四、实现界面联动

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

7fc0f9f2-03db-11ed-ba43-dac502259ad0.gif

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描述、循环渲染、状态数据管理等机制,赶快趁热打铁,开发更多有趣的应用吧!

原文标题:基于eTS高效开发HarmonyOS课程类应用

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    6511

    浏览量

    87589
  • API接口
    +关注

    关注

    1

    文章

    79

    浏览量

    10313
  • HarmonyOS
    +关注

    关注

    79

    文章

    1814

    浏览量

    29256

原文标题:基于eTS高效开发HarmonyOS课程类应用

文章出处:【微信号:HarmonyOS_Dev,微信公众号:HarmonyOS开发者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    鸿蒙开发学习:【ets_frontend组件】

    ets_frontend组件采用命令行交互方式,支持将JavaScript代码转换为方舟字节码文件,使其能够在方舟运行时上运行。支持Windows/Linux/MacOS平台。方舟前端工具在linux平台上可通过全量编译或指定编译前端工具链获取。
    的头像 发表于 03-10 19:58 68次阅读
    鸿蒙<b class='flag-5'>开发</b>学习:【<b class='flag-5'>ets</b>_frontend组件】

    鸿蒙实战项目开发:【短信服务】

    ; 需授予短信发送权限且插入SIM卡才可成功发送短信,有预置短信内容,每次退出应用数据会清空,未添加存储功能,发送短信为默认卡发送。 工程目录 entry/src/main/ets
    发表于 03-03 21:29

    arkcompiler_runtime_core/static_core/runtime和arkcompiler_ets_runtime有什么关联

    arkcompiler_runtime_core/static_core/runtime有内存分配和垃圾回收,arkcompiler_ets_runtime也有独立的内存管理和垃圾回收。 这两个库之间是什么关系和作用
    发表于 01-10 21:39

    OpenHarmony应用开发—ArkUI组件集合

    介绍 本示例为ArkUI中组件、通用、动画、全局方法的集合。 工程目录 entry/src/main/ets/ |---component
    发表于 09-22 14:56

    OpenHarmony—应用间HSP开发指导

    的方式使用应用间HSP提供的能力,从而实现应用自身所需要的功能。 注意事项 应用间HSP的代码会运行在开发者应用的进程中,调用相关代码时,需要做好异常捕获与容错处理,防止由于应用间HSP功能异常导致
    发表于 09-11 19:02

    HarmonyOS Codelab 优秀样例——购物应用,体验一次开发多端部署魅力

    一. 样例介绍 本篇Codelab基于自适应布局和响应式布局,实现购物应用在手机、折叠屏、平板不同屏幕尺寸设备上按不同设计显示。通过三层工程结构组织代码,实现一次开发,多端部署 。 手机运行效果
    发表于 08-28 15:57

    鸿蒙元服务万能卡片开发-stage模型和fa模型的卡片区别

    一、项目类型 Application: 应用开发 Atomic Service:原子化服务开发 这里选择Empty Ability模板创建项目。 二、Stage模型卡片开发 Api:9
    发表于 05-22 14:20

    #深入浅出学习eTs#(八)“猜大小”小游戏

    本项目Gitee仓地址:[深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com)](   上一章节提到的模拟器存在的BUG问题,目前没有办法直接改善,本来打算直接使用鸿蒙远程设备
    的头像 发表于 05-17 15:08 725次阅读
    #深入浅出学习<b class='flag-5'>eTs</b>#(八)“猜大小”小游戏

    #深入浅出学习eTs#(十)蓝药丸还是红药丸

    本项目Gitee仓地址: 深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com) 一、需求分析 我们本章的内容选择致敬黑客帝国,如果你处于主角的立场,你会选择蓝药丸还是红药丸呢?本章
    的头像 发表于 05-17 15:07 685次阅读
    #深入浅出学习<b class='flag-5'>eTs</b>#(十)蓝药丸还是红药丸

    ETS-Lindgren为襄阳达安汽车检测中心提供先进的EMC测试暗室

    E-Motor暗室旨在优化高压部件的测试,包括但不限于电池、空调、高压动力转向和压缩机。其屏蔽采用ETS-Lindgren S101板形式,外部支撑结构符合地震带7级烈度要求。
    的头像 发表于 05-15 11:43 1570次阅读
    <b class='flag-5'>ETS</b>-Lindgren为襄阳达安汽车检测中心提供先进的EMC测试暗室

    深入浅出学习eTs之九宫格密码锁功能实现

    本项目Gitee仓地址:深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com) 一、需求分析 相信没有人没有使用过九宫格解锁吧,从智能机开始迸发的时期到现在,我们本期就要做一个自己
    的头像 发表于 05-13 13:25 1041次阅读
    深入浅出学习<b class='flag-5'>eTs</b>之九宫格密码锁功能实现

    #深入浅出学习eTs#(九)变红码?专属二维码生成

    本项目Gitee仓地址: 深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com) 一、需求分析 我们本章的内容是要制作一个可以随着自己想要内容而变化的一个二维码,通过输入框输入
    的头像 发表于 05-13 13:21 1005次阅读
    #深入浅出学习<b class='flag-5'>eTs</b>#(九)变红码?专属二维码生成

    深入浅出学习eTs(七)如何判断密码是否正确

    本项目Gitee仓地址: 深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com) 一、基本界面 本项目基于#深入浅出学习eTs#(四)登陆界面UI,继续进行,实现一个判断的功能
    的头像 发表于 05-13 13:20 646次阅读
    深入浅出学习<b class='flag-5'>eTs</b>(七)如何判断密码是否正确

    深入浅出学习eTs(五)eTs语言初识

    基于TS扩展的声明式开发范式的方舟开发框架是一套开发极简、高性能、跨设备应用的UI开发框架,支持开发者高效的构建跨设备应用UI界面。
    的头像 发表于 05-13 13:19 1839次阅读
    深入浅出学习<b class='flag-5'>eTs</b>(五)<b class='flag-5'>eTs</b>语言初识

    深入浅出学习eTs(一)模拟器/真机环境搭建

    本项目的Gitee仓地址: 深入浅出eTs学习: 带大家深入浅出学习eTs (gitee.com) (之前有些意外,数据丢失了,现在重新发,且不参与任何活动,在第一篇说明一下,之后就不
    的头像 发表于 05-13 13:17 1139次阅读
    深入浅出学习<b class='flag-5'>eTs</b>(一)模拟器/真机环境搭建