隨著HarmonyOS 3.0 Beta版的發(fā)布,API Version 8新增了大批JS/eTS API接口,相信很多開發(fā)者已經(jīng)迫不及待想體驗基于eTS的HamronyOS應(yīng)用開發(fā)。本期Codelab,我們將基于API Version 8實現(xiàn)一個HarmonyOS課程類應(yīng)用,幫助大家學(xué)習(xí)eTS的聲明式UI描述、循環(huán)渲染、狀態(tài)數(shù)據(jù)管理等機制,體驗基于eTS的極簡高效開發(fā)。
一、整體介紹
在課程類應(yīng)用界面中,左側(cè)為課程分類導(dǎo)航欄,右側(cè)為各個類別的課程內(nèi)容。當(dāng)用戶上下滑動右側(cè)課程內(nèi)容時,左側(cè)導(dǎo)航欄會跳轉(zhuǎn)至對應(yīng)的課程分類。當(dāng)用戶點擊左側(cè)導(dǎo)航欄的課程分類時,會高亮顯示點擊的內(nèi)容,且右側(cè)課程內(nèi)容會跳轉(zhuǎn)至對應(yīng)類別的課程列表。
那么如何基于eTS高效實現(xiàn)這樣一個HarmonyOS課程類應(yīng)用?下面我們將從聲明式UI描述、循環(huán)渲染數(shù)據(jù)、狀態(tài)數(shù)據(jù)管理三個維度來解析。
1. 聲明式UI描述
界面布局是UI界面的骨架,決定了應(yīng)用界面的交互和視覺風(fēng)格。本示例中我們將通過eTS的一系列基礎(chǔ)組件以聲明式方式進(jìn)行組合和擴展,并采用接近自然語義的編程語法直觀地描述UI界面,包括參數(shù)構(gòu)造配置、屬性配置、事件配置以及子組件配置等。
相較于基于Java的命令式開發(fā),eTS采用更接近自然語義的聲明式編程語法,讓開發(fā)者可以更直觀地描述UI界面,有效地降低了開發(fā)者的上手成本,極大程度地提升了UI界面的構(gòu)建效率,實現(xiàn)極簡高效開發(fā)。
2. 循環(huán)渲染數(shù)據(jù)
數(shù)據(jù)模型是UI界面的肉體,描述了界面中數(shù)據(jù)的靜態(tài)特征、動態(tài)行為和約束條件。本示例中我們將通過eTS直觀地定義界面中各個模塊的數(shù)據(jù)模型,包含名稱、標(biāo)識、圖片鏈接等,并根據(jù)數(shù)據(jù)模型寫入對應(yīng)的數(shù)據(jù)。最后使用eTS提供的循環(huán)渲染機制(ForEach)將寫入的數(shù)據(jù)循環(huán)渲染至對應(yīng)的界面中。
相較于基于Java的命令式開發(fā),eTS在渲染數(shù)據(jù)時UI的更新不需要開發(fā)者使用代碼主動刷新,而是交給框架層自動處理,開發(fā)者不必關(guān)心框架如何實現(xiàn)UI繪制和渲染,實現(xiàn)界面數(shù)據(jù)的高效渲染。
3. 狀態(tài)數(shù)據(jù)管理
聯(lián)動效果是UI界面的靈魂,實現(xiàn)了界面中布局與數(shù)據(jù)的動態(tài)交互,本示例中我們將使用eTS提供的狀態(tài)數(shù)據(jù)管理機制通過裝飾組件擁有的狀態(tài)屬性,當(dāng)裝飾的變量更改時,組件會重新渲染更新UI界面數(shù)據(jù),從而實現(xiàn)聯(lián)動效果。
相較于基于Java的命令式開發(fā),eTS通過功能不同的裝飾器給開發(fā)者提供了清晰的頁面更新渲染流程和管道。開發(fā)者要做的就是定義數(shù)據(jù)與UI的映射關(guān)系,后面只需要通過狀態(tài)裝飾器監(jiān)聽數(shù)據(jù)的狀態(tài),UI即可自動刷新,這極大地減輕了程序員對UI的維護(hù)工作。
以上就是實現(xiàn)課程類應(yīng)用的核心原理,下面我們將為大家?guī)砀鞑糠值木唧w實現(xiàn)。
二、搭建界面布局
eTS提供了多種布局方式,不僅保留了經(jīng)典的彈性布局能力,也提供了列表、宮格、柵格布局和適應(yīng)多分辨率場景開發(fā)的原子布局能力。如圖1所示,本示例中整體布局使用Row沿水平方向布局容器,并設(shè)置背景顏色為白色,Row內(nèi)部嵌套Scroll及List容器分別作為應(yīng)用界面的導(dǎo)航欄布局和課程內(nèi)容布局,下面我們將為你一一道來。 圖1 整體布局
1. 導(dǎo)航欄布局
應(yīng)用界面的導(dǎo)航欄使用可滾動的容器組件Scroll來實現(xiàn),Scroll內(nèi)嵌Text組件用于顯示“課程分類”名稱,如圖2所示:
圖2 導(dǎo)航欄布局
Scroll容器必須內(nèi)置一個子組件,我們使用了垂直方向的布局容器Column,并設(shè)置填充高度為height('100%')?!罢n程分類”名稱使用Text組件實現(xiàn),并設(shè)置文字顏色為fontColor(0x696969)、文字大小為fontSize(16)、文字對齊方式為textAlign(TextAlign.Center)居中顯示、高度為height(60)、寬度為width('100%')。
相關(guān)代碼如下:
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. 課程內(nèi)容布局
應(yīng)用的課程內(nèi)容部分的布局使用List列表容器來實現(xiàn),并使用ForEach循環(huán)渲染listArray(課程內(nèi)容)數(shù)據(jù),如圖3所示,課程內(nèi)容布局包含頭部和課程信息兩部分(頭部和左邊的導(dǎo)航欄對應(yīng)),下面我們將分別介紹頭部及課程信息的布局的實現(xiàn)。
圖3 課程內(nèi)容布局
(1) 頭部布局
頭部使用Text組件實現(xiàn),并設(shè)置了文字顏色為fontColor(0x696969)、文字大小為fontSize(20)、高度為height(40)、寬度為width('100%')填充、內(nèi)邊距為padding({ left: 10 })、背景顏色為backgroundColor(0xefefef)。同時,頭部的ListItem設(shè)置了sticky(Sticky.Normal)屬性,使其滑動到頂部時可以呈現(xiàn)固定的效果。代碼如下:
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堆疊容器,高度設(shè)置為height(120),設(shè)置子組件在容器內(nèi)的對齊方式為Alignment.TopStart。Stack組件內(nèi)嵌Image、Text、Divider組件,用于呈現(xiàn)課程圖片、課程標(biāo)題、課程價格及分割線等信息。具體如下:
●課程的圖片使用Image組件呈現(xiàn),設(shè)置寬度為width(130),高度為height(100),圖片的縮放類型為objectFit(ImageFit.Fill),使圖片填充滿組件,并設(shè)置左邊、頂部邊距均10,使其組件居中對齊。代碼如下:
Image(item.imageUrl) .objectFit(ImageFit.Cover) .width(130) .height(100) .margin({ left: 10, top: 10 })(左右滑動,查看更多)
●課程名稱使用Text組件,設(shè)置文字顏色為fontColor(0x363636)、文字大小為fontSize(14),最大顯示行數(shù)為maxLines(2)兩行,文本超長時的顯示方式為TextOverflow.Clip,意為進(jìn)行裁剪顯示。代碼如下:
Text(item.courseName) .fontColor(0x363636) .fontSize(14) .margin({ left: 150, top: 12 }) .maxLines(2) .textOverflow({ overflow: TextOverflow.Clip })
(左右滑動,查看更多)
●課程的價格使用Text組件,設(shè)置文字顏色為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組件實現(xiàn),并設(shè)置了分割線顏色為color(0xefefef)、分割線寬度為strokeWidth(0.7)、左右邊距margin({ left: 10, right: 10 })均為10,并使用絕對定位position({ x: 0, y: '100%' })和錨點定位markAnchor({ x: 0, y: '100%' })使分割線呈現(xiàn)在Stack容器最底部。代碼如下:
Divider() .margin({ left: 10, right: 10 }) .color(0xefefef) .strokeWidth(0.7) .position({ x: 0, y: '100%' }) .markAnchor({ x: 0, y: '100%' })
(左右滑動,查看更多)
至此,我們已經(jīng)實現(xiàn)了界面布局,此時界面只是一個沒有任何內(nèi)容的骨架。接下來我們將為應(yīng)用界面添加數(shù)據(jù)模型。
三、構(gòu)建數(shù)據(jù)模型
本章節(jié)我們將為大家介紹本示例中數(shù)據(jù)模型的定義、數(shù)據(jù)的預(yù)置以及數(shù)據(jù)的加載。
1. 定義數(shù)據(jù)模型
本示例需定義兩個數(shù)據(jù)模型,分別是應(yīng)用界面中左側(cè)導(dǎo)航欄的“課程分類”和右側(cè)的“課程內(nèi)容”。其中:
●導(dǎo)航欄“課程分類”定義了名稱(superName)和位置(position)屬性。數(shù)據(jù)模型定義如下:
export class TabItem { position: number; // 點擊該分類時課程內(nèi)容滑動到的位置 superName: string; // 課程分類標(biāo)題 constructor(position: number, superName: string) { this.position = position; this.superName = superName; }}(左右滑動,查看更多)
●“課程內(nèi)容”定義了課程的名稱(courseName)、課程的圖片地址(imageUrl)、課程的價格(price)、判斷是否為此類別課程頭部的變量(tag)、課程所對應(yīng)課程類別的索引位置(index),數(shù)據(jù)模型定義如下:
export class CourseItem { tag: boolean; // 是否此類別課程的頭部 index: number; // 課程所對應(yīng)課程類別的索引位置 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. 預(yù)置數(shù)據(jù)
在entry/src/main/ets/MainAbility/Model.ets文件中,放入準(zhǔn)備好的模擬數(shù)據(jù),其中,superId是課程分類的唯一標(biāo)識、id是課程內(nèi)容的唯一標(biāo)識。格式如下:
const LinkData: any[] = [ { "superId": 1, "superName": "熱門課程", "id": 1, "courseName": "應(yīng)用市場介紹", "imageUrl": "/image/image1.jpg", "price": 0 }, { "superId": 1, "superName": "熱門課程", "id": 2, "courseName": "上架流程", "imageUrl": "/image/image2.jpg", "price": 100 }, ... ](左右滑動,查看更多)
3. 加載數(shù)據(jù)更新UI
本章節(jié)將介紹如何加載本地構(gòu)造的模擬數(shù)據(jù)并呈現(xiàn)到界面。
(1) 加載數(shù)據(jù)
在index.ets文件中,通過getLinkData()獲取預(yù)置數(shù)據(jù)。
aboutToAppear() { // 延時數(shù)據(jù)加載 setTimeout(() => { let linkDataItem = getLinkData(); this.tabArray = linkDataItem.tabArray; this.listArray = linkDataItem.listArray; this.requestSuccess = true; }, 2000)}
(左右滑動,查看更多)
(2) 渲染
●導(dǎo)航欄使用ForEach循環(huán)渲染tabArray(課程分類)數(shù)據(jù)。這里的ForEach的第一個參數(shù)需要使用數(shù)組的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) }})(左右滑動,查看更多)
●課程內(nèi)容使用ForEach循環(huán)渲染listArray(課程內(nèi)容)數(shù)據(jù)。代碼如下:
ForEach(this.listArray, item => { if (item.tag) { ListItem() { ...... }.sticky(Sticky.Normal) } else { ListItem() { Stack({ alignContent: Alignment.TopStart }) { ...... }.height(120) } }}, item => '' + item)(左右滑動,查看更多)
通過上文的介紹,我們已經(jīng)實現(xiàn)了應(yīng)用界面的布局以及界面數(shù)據(jù)的呈現(xiàn),此時界面就像沒有靈魂的軀殼。下面我們將為大家介紹應(yīng)用中聯(lián)動效果的實現(xiàn)。
四、實現(xiàn)界面聯(lián)動
本示例中的聯(lián)動效果包括導(dǎo)航欄高亮顯示、滑動課程內(nèi)容對應(yīng)導(dǎo)航欄變化、點擊導(dǎo)航欄課程分類跳轉(zhuǎn)到對應(yīng)課程內(nèi)容,下面我們將一一道來。
1. 導(dǎo)航欄高亮顯示
實現(xiàn)導(dǎo)航欄高亮顯示,主要通過@State裝飾器監(jiān)聽導(dǎo)航欄課程分類的索引值的狀態(tài)變化,當(dāng)用戶滑動課程內(nèi)容或點擊導(dǎo)航欄,對應(yīng)課程分類的索引值發(fā)生變化,此時將調(diào)用build方法進(jìn)行UI刷新,從而實現(xiàn)導(dǎo)航欄背景色的修改。相關(guān)代碼如下:
@State index: number= 0; // 導(dǎo)航欄課程分類的索引Text(item.data.superName) .backgroundColor(this.index == item.index ? 0xffffff : null)
2. 右邊滑動,左邊變化
滑動右邊課程內(nèi)容,對應(yīng)左邊導(dǎo)航欄變化,主要通過onScrollIndex()事件來判斷當(dāng)前課程內(nèi)容所屬的課程分類,當(dāng)用戶滑動課程內(nèi)容時,對應(yīng)課程內(nèi)容的索引值發(fā)生變化,導(dǎo)航欄的課程分類的索引值也隨之變化。相關(guān)代碼如下:
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. 左邊點擊,右邊跳轉(zhuǎn)
點擊左邊導(dǎo)航欄跳轉(zhuǎn)到對應(yīng)課程內(nèi)容,主要通過onClick()事件監(jiān)聽用戶點擊,當(dāng)用戶點擊導(dǎo)航欄,scrollToIndex()方法會根據(jù)點擊的導(dǎo)航欄課程分類的索引值跳轉(zhuǎn)到對應(yīng)的課程內(nèi)容界面。相關(guān)代碼如下:
Text(item.data.superName) .onClick(() => { if (this.index != item.index) { this.index = item.index this.scroller.scrollToIndex(item.data.position) } })
以上就是本期全部內(nèi)容,通過本期Codelab的學(xué)習(xí),相信你已經(jīng)掌握了eTS的聲明式UI描述、循環(huán)渲染、狀態(tài)數(shù)據(jù)管理等機制,趕快趁熱打鐵,開發(fā)更多有趣的應(yīng)用吧!
原文標(biāo)題:基于eTS高效開發(fā)HarmonyOS課程類應(yīng)用
-
數(shù)據(jù)
+關(guān)注
關(guān)注
8文章
7030瀏覽量
89038 -
API接口
+關(guān)注
關(guān)注
1文章
84瀏覽量
10438 -
HarmonyOS
+關(guān)注
關(guān)注
79文章
1975瀏覽量
30202
原文標(biāo)題:基于eTS高效開發(fā)HarmonyOS課程類應(yīng)用
文章出處:【微信號:HarmonyOS_Dev,微信公眾號:HarmonyOS開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論