介紹
本篇Codelab使用常用組件、頁(yè)面路由router實(shí)現(xiàn)購(gòu)物應(yīng)用,包含以下功能:
- 使用toolbar、toolbar-item組件實(shí)現(xiàn)“首頁(yè)”,“新品”,“購(gòu)物車”,“我的”頁(yè)面切換。
- 使用list組件,展示購(gòu)物車?yán)锏?a target="_blank">商品。
- 使用swiper組件,實(shí)現(xiàn)圖片自動(dòng)輪播。
- 使用panel組件,展示商品規(guī)格。
- 使用自定義組件,提高代碼的可讀性。

相關(guān)概念
- [swiper]:滑動(dòng)容器,提供切換子組件顯示的能力。
- [input]:交互式組件,包括單選框,多選框,按鈕和單行文本輸入框。
- [search]:搜索框組件,用于提供用戶搜索內(nèi)容的輸入?yún)^(qū)域。
- [toolbar]:工具欄。放在界面底部,用于展示針對(duì)當(dāng)前界面的操作選項(xiàng)。
- [toolbar-item]:工具欄[toolbar]子組件。 用于展示工具欄上的一個(gè)操作選項(xiàng)。
- [自定義組件]:自定義組件是用戶根據(jù)業(yè)務(wù)需求,將已有的組件組合,封裝成的新組件,可以在工程中多次調(diào)用,從而提高代碼的可讀性。
環(huán)境搭建
軟件要求
- [DevEco Studio]版本:DevEco Studio 3.1 Release及以上版本。
- OpenHarmony SDK版本:API version 9及以上版本。
硬件要求
- 開(kāi)發(fā)板類型:[潤(rùn)和RK3568開(kāi)發(fā)板]。
- OpenHarmony系統(tǒng):3.2 Release及以上版本。
環(huán)境搭建
完成本篇Codelab我們首先要完成開(kāi)發(fā)環(huán)境的搭建,本示例以RK3568開(kāi)發(fā)板為例,參照以下步驟進(jìn)行:
- [獲取OpenHarmony系統(tǒng)版本]:標(biāo)準(zhǔn)系統(tǒng)解決方案(二進(jìn)制)。以3.2 Release版本為例:

- 搭建燒錄環(huán)境。
- [完成DevEco Device Tool的安裝]
- [完成RK3568開(kāi)發(fā)板的燒錄](méi)
- 搭建開(kāi)發(fā)環(huán)境。

代碼結(jié)構(gòu)解讀
本篇Codelab只對(duì)核心代碼進(jìn)行講解,對(duì)于完整代碼,我們會(huì)在【gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md】中提供。由于本篇Codelab頁(yè)面較多,因此component和pages目錄下只展示“購(gòu)物主頁(yè)面”的hml、js、css。
`HarmonyOS與OpenHarmony鴻蒙文檔籽料:mau123789是v直接拿`
├──entry/src/main/js // 代碼區(qū)
│ └──MainAbility
│ ├──common
│ │ ├──constant
│ │ │ └──commonConstants.js // 公共常量類
│ │ └──images // 圖片區(qū)
│ ├──component
│ │ ├──backComponent // 后退子組件
│ │ ├──commonButton // 支付按鈕子組件
│ │ ├──commonToolbar // 導(dǎo)航欄子組件
│ │ ├──home // 購(gòu)物主頁(yè)子組件
│ │ ├──likedCards // 猜你喜歡卡片子組件
│ │ ├──myInfo // 我的子組件
│ │ ├──newProduct // 新品子組件
│ │ ├──orderReusableCom // 用戶商品信息子組件
│ │ ├──productBuyInfo // 購(gòu)買商品卡片子組件
│ │ ├──shoppingCart // 購(gòu)物車子組件
│ │ └──subtitle // 副標(biāo)題子組件
│ ├──i18n
│ │ ├──en-US.json // 英文國(guó)際化
│ │ └──zh-CN.json // 中文國(guó)際化
│ ├──pages
│ │ ├──allOrders // 全部訂單頁(yè)
│ │ ├──homePage // 購(gòu)物主頁(yè)
│ │ │ ├──homePage.css // 購(gòu)物主頁(yè)面樣式
│ │ │ ├──homePage.hml // 購(gòu)物主頁(yè)面
│ │ │ └──homePage.js // 購(gòu)物主頁(yè)面邏輯
│ │ ├──launchPage // 啟動(dòng)頁(yè)
│ │ ├──pendingPayment // 待支付頁(yè)
│ │ ├──productDetails // 產(chǎn)品詳情頁(yè)
│ │ └──sureOrder // 確定訂單頁(yè)
│ └──app.js // 程序入口
└──entry/src/main/resources // 應(yīng)用資源目錄
構(gòu)建購(gòu)物應(yīng)用首頁(yè)
本篇Codelab選取購(gòu)物應(yīng)用的主頁(yè)面、購(gòu)物車頁(yè)面、以及導(dǎo)航欄進(jìn)行詳細(xì)的講解,對(duì)于完整代碼,可在gitee源碼中進(jìn)行查看。
購(gòu)物應(yīng)用的主頁(yè)面主要由界面底部導(dǎo)航欄和導(dǎo)航欄上的內(nèi)容組成。效果如圖所示:

< !-- homePage.hml -- >
< element name="home" src="http://www.brongaenegriffin.com/images/chaijie_default.png" >< /element >
< element name="new-product" src="http://www.brongaenegriffin.com/images/chaijie_default.png" >< /element >
< element name="shopping-cart" src="http://www.brongaenegriffin.com/images/chaijie_default.png" >< /element >
< element name="my-info" src="http://www.brongaenegriffin.com/images/chaijie_default.png" >< /element >
< element name="common-toolbar" src="http://www.brongaenegriffin.com/images/chaijie_default.png" >< /element >
< div class="container" >
< !-- 主頁(yè)面 -- >
< home if="{{ tag === homePageIndex }}" >< /home >
< !-- 新品頁(yè)面 -- >
< new-product if="{{ tag === newProductIndex }}" >< /new-product >
< !-- 購(gòu)物車頁(yè)面 -- >
< shopping-cart if="{{ tag === shoppingCartIndex }}" >< /shopping-cart >
< !-- 我的頁(yè)面 -- >
< my-info if="{{ tag === myInfoIndex }}" >< /my-info >
< !-- 導(dǎo)航欄 -- >
< common-toolbar tag="{{ tag }}" @switch-toolbar="switchToolbar" >< /common-toolbar >
< /div >
底部導(dǎo)航欄:由“主頁(yè)”、“新品”、“購(gòu)物車”以及“我的”頁(yè)面組成,點(diǎn)擊導(dǎo)航欄內(nèi)容,展示所點(diǎn)擊模塊的內(nèi)容。
// homePage.js
import CommonConstants from '../../common/constant/commonConstants';
export default {
data: {
// 頁(yè)面默認(rèn)展示主頁(yè),tag是主頁(yè)面的索引
tag: 1,
// 主頁(yè)面索引
homePageIndex: CommonConstants.HOME_PAGE_INDEX,
// 新品頁(yè)面索引
newProductIndex: CommonConstants.NEW_PRODUCT_INDEX,
// 購(gòu)物車頁(yè)面索引
shoppingCartIndex: CommonConstants.SHOPPING_CART_INDEX,
// 我的頁(yè)面索引
myInfoIndex: CommonConstants.MY_INFO_INDEX
},
/**
* 切換導(dǎo)航欄內(nèi)容
*
* @param value 子組件傳過(guò)來(lái)的索引
*/
switchToolbar(value) {
this.tag = value.detail.index;
}
}
子組件:導(dǎo)航欄的使用
導(dǎo)航欄由“主頁(yè)”、“新品”、“購(gòu)物車”以及“我的”組成,點(diǎn)擊導(dǎo)航欄對(duì)應(yīng)的子組件,頁(yè)面會(huì)展示對(duì)應(yīng)模塊的內(nèi)容。效果如圖所示:

在父組件homePage.hml中使用@switch-toolbar="switchToolbar"綁定子組件的事件,用于接收子組件傳過(guò)來(lái)的索引,通過(guò)if判斷,從而展示索引對(duì)應(yīng)的頁(yè)面。
!-- homePage.hml -- >
...
div class="container" >
!-- 主頁(yè)面 -- >
home if="{{ tag === homePageIndex }}" > /home >
!-- 新品頁(yè)面 -- >
new-product if="{{ tag === newProductIndex }}" > /new-product >
!-- 購(gòu)物車頁(yè)面 -- >
shopping-cart if="{{ tag === shoppingCartIndex }}" > /shopping-cart >
!-- 我的頁(yè)面 -- >
my-info if="{{ tag === myInfoIndex }}" > /my-info >
!-- 導(dǎo)航欄 -- >
common-toolbar tag="{{ tag }}" @switch-toolbar="switchToolbar" > /common-toolbar >
/div >
!-- commonToolbar.hml -- >
div class="container" >
toolbar class="toolbar" >
toolbar-item value="{{ $t(toolbarName.home) }}" @click="switchToolbar(homePageIndex)"
icon="{{ tag === homePageIndex ? commonIcon.home : commonIcon.homeDisable }}" >
/toolbar-item >
toolbar-item value="{{ $t(toolbarName.newProduct) }}" @click="switchToolbar(newProductIndex)"
icon="{{ tag === newProductIndex ? commonIcon.newProduct : commonIcon.newProductDisable }}" >
/toolbar-item >
toolbar-item value="{{ $t(toolbarName.shoppingCart) }}" @click="switchToolbar(shoppingCartIndex)"
icon="{{ tag === shoppingCartIndex ? commonIcon.shoppingCart : commonIcon.shoppingCartDisable }}" >
/toolbar-item >
toolbar-item value="{{ $t(toolbarName.me) }}" @click="switchToolbar(myInfoIndex)"
icon="{{ tag === myInfoIndex ? commonIcon.me : commonIcon.meDisable }}" >
/toolbar-item >
/toolbar >
/div >
在子組件commonToolbar.js中通過(guò)this.$emit('switchToolbar', {info: value})觸發(fā)事件并向上傳遞參數(shù),homePage.js中的switchToolbar方法接收子組件傳過(guò)來(lái)的索引。在子組件commonToolbar.js文件中定義props,props用于組件之間的數(shù)據(jù)通信,當(dāng)父組件中的tag發(fā)生變化的時(shí)候,子組件也會(huì)隨之響應(yīng),然后改變toolbar-item中icon的顏色。
// homePage.js
import CommonConstants from '../../common/constant/commonConstants';
export default {
data: {
// 頁(yè)面默認(rèn)展示主頁(yè),tag是主頁(yè)面的索引
tag: 1,
...
},
/**
* 切換導(dǎo)航欄內(nèi)容
*
* @param value 子組件傳過(guò)來(lái)的索引
*/
switchToolbar(value) {
this.tag = value.detail.index;
}
}
// commonToolbar.js
import CommonConstants from '../../common/constant/commonConstants';
export default {
props: ['tag'],
data: {
commonIcon: CommonConstants.COMMON_TOOLBAR_ICON,
toolbarName: CommonConstants.COMMON_TOOLBAR_NAME,
// 主頁(yè)面索引
homePageIndex: CommonConstants.HOME_PAGE_INDEX,
// 新品頁(yè)面索引
newProductIndex: CommonConstants.NEW_PRODUCT_INDEX,
// 購(gòu)物車頁(yè)面索引
shoppingCartIndex: CommonConstants.SHOPPING_CART_INDEX,
// 我的頁(yè)面索引
myInfoIndex: CommonConstants.MY_INFO_INDEX
},
/**
* 向父組件傳值
*
* @param index 選中子模塊的索引
*/
switchToolbar(index) {
this.$emit('switchToolbar', {
index: index
});
}
}
構(gòu)建購(gòu)物車頁(yè)面
購(gòu)物車頁(yè)面由頂部標(biāo)題欄、購(gòu)物車商品列表、猜你喜歡的商品列表三部分組成,并以子組件的形式顯示在主頁(yè)面中。其中,購(gòu)物車商品列表使用list組件和for循環(huán),實(shí)現(xiàn)對(duì)多條商品數(shù)據(jù)進(jìn)行展示。猜你喜歡的商品列表是通過(guò)引用自定義組件實(shí)現(xiàn)的。效果如圖所示:

< !-- shoppingCart.hml -- >
< element name="liked-cards" src="../../component/likedCards/likedCards.hml" >< /element >
< div class="container" >
< div class="top" >
< !-- 頂部導(dǎo)航標(biāo)題欄 -- >
< div class="top-title" >
< text class="shopping-cart" >{{ $t('strings.shopping_cart') }}< /text >
< text class="edit" >{{ $t('strings.edit') }}< /text >
< /div >
< !-- 購(gòu)物車商品列表 -- >
< div class="top-list" >
< div class="list-title" >
< input class="all-checkbox" type="checkbox" checked="{{ isAllSelect }}" @change="checkboxOnChange" >
< /input >
< image class="my-icon-size" src="{{ person }}" >< /image >
< text class="mall-self-operated" >{{ $t('strings.mall_self_operated') }}< /text >
< /div >
< list class="list" >
< list-item for="{{ (index, item) in shoppingListData }}" class="list-item" >
< div class="list-content" >
< input class="checkbox" type="checkbox" checked="{{ item.isSelect }}" >< /input >
< image class="product-pictures" src="{{ item.image }}" >< /image >
< div class="box-content" >
< text class="product-title" >{{ $t(item.title) }}< /text >
< text class="product-subtitle" >{{ $t(item.subtitle) }}< /text >
< div class="content-price" >
< text class="product-price" >{{ item.price }}< /text >
< div class="price-num" >
< image class="my-icon-size" @click="subtractNum(index)" src="http://www.brongaenegriffin.com/images/chaijie_default.png" >
< /image >
< text class="product-num" >{{ item.num }}< /text >
< image class="my-icon-size" src="{{ commonIcon.increaseIcon }}"
@click="addNum(index)" >
< /image >
< /div >
< /div >
< /div >
< /div >
< /list-item >
< /list >
< /div >
< /div >
< !-- 猜你喜歡商品列表 -- >
< div class="middle-card" >
< liked-cards >< /liked-cards >
< /div >
< /div >
- 點(diǎn)擊“商品自營(yíng)”頭像前的多選框,會(huì)觸發(fā)checkboxOnChange()方法,頁(yè)面會(huì)勾選/不勾選購(gòu)物車的中所有商品。
- 點(diǎn)擊“+”按鈕會(huì)觸發(fā)addNum()方法,增加單件商品的數(shù)量。
- 點(diǎn)擊“-”按鈕會(huì)觸發(fā)subtractNum()方法,減少單件商品的數(shù)量。
// shoppingCart.js
import CommonConstants from '../../common/constant/commonConstants';
export default {
data: {
isAllSelect: false,
shoppingListData: CommonConstants.SHOPPING_LIST_DATA,
commonIcon: CommonConstants.SHOPPING_CART_ICON,
person: CommonConstants.COMMON_ICON.person
},
/**
* 購(gòu)物車商品全選/非全選
*/
checkboxOnChange() {
this.isAllSelect = !this.isAllSelect;
this.shoppingListData.filter((item) = > {
item.isSelect = this.isAllSelect;
});
},
/**
* 勾選單個(gè)商品
*
* @param subscript 選中商品的索引
* @param event 單選框事件
*/
singleAnswer(subscript, event) {
// 修改商品的選擇狀態(tài)
this.shoppingListData.forEach((item, index) = > {
if (index === subscript) {
item.isSelect = event.checked;
}
})
// 檢查購(gòu)物車中的所有商品是否都被選中
let selectAll = this.shoppingListData.every(item = > item.isSelect === true);
if (selectAll === true) {
this.isAllSelect = true;
} else {
this.isAllSelect = false;
}
},
/**
* 減少商品數(shù)量邏輯
*
* @param value 當(dāng)前商品的數(shù)量
*/
subtractNum(value) {
if (this.shoppingListData[value].num > 0) {
this.shoppingListData[value].num--;
}
},
/**
* 增加商品數(shù)量邏輯
*
* @param value 當(dāng)前商品的數(shù)量
*/
addNum(value) {
this.shoppingListData[value].num++;
}
}
審核編輯 黃宇
-
鴻蒙
+關(guān)注
關(guān)注
60文章
2924瀏覽量
45569 -
OpenHarmony
+關(guān)注
關(guān)注
33文章
3942瀏覽量
20914
發(fā)布評(píng)論請(qǐng)先 登錄
HarmonyOS開(kāi)發(fā)案例:【購(gòu)物車app】
HarmonyOS IoT 硬件開(kāi)發(fā)案例分享
【HarmonyOS】開(kāi)發(fā)跨設(shè)備的鴻蒙(HarmonyOS) App
【HarmonyOS】開(kāi)發(fā)跨設(shè)備的鴻蒙(HarmonyOS)App
如何優(yōu)雅地開(kāi)發(fā)HarmonyOS APP應(yīng)用
【潤(rùn)和直播課預(yù)告@華為開(kāi)發(fā)者學(xué)院】HarmonyOS設(shè)備開(kāi)發(fā)基礎(chǔ)課程|HiSpark WiFi-IoT 智能小車套件開(kāi)發(fā)案例
【基于HarmonyOS開(kāi)發(fā)購(gòu)物應(yīng)用】AnBetter Codelab第二期記錄帖
【基于HarmonyOS開(kāi)發(fā)購(gòu)物應(yīng)用】jack_606 Codelab第二期記錄帖
【基于HarmonyOS開(kāi)發(fā)購(gòu)物應(yīng)用】SetllatWood Codelab第二期記錄帖
使用JS實(shí)現(xiàn)一款簡(jiǎn)單的HarmonyOS購(gòu)物應(yīng)用
harmonyOS開(kāi)發(fā)的APP如何訪問(wèn)Webservice?
App開(kāi)發(fā)案例教程PDF電子書(shū)免費(fèi)下載
許思維老師HarmonyOS IoT硬件開(kāi)發(fā)案例分享
華為開(kāi)發(fā)者分論壇HarmonyOS學(xué)生公開(kāi)課-OpenHarmony Codelabs開(kāi)發(fā)案例
HarmonyOS 代碼工坊的指尖開(kāi)發(fā),讓 APP 開(kāi)發(fā)所見(jiàn)即所得
HarmonyOS開(kāi)發(fā)案例:【購(gòu)物APP】
評(píng)論