目前電商領(lǐng)域有兩款比較出名的開(kāi)源電商網(wǎng)站解決方案,分別是基于 Angular 開(kāi)發(fā)框架,代號(hào)為 Spartacus 的開(kāi)源項(xiàng)目,以及基于 Vue 的 Vue Storefront.


作為 Spartacus 開(kāi)源項(xiàng)目的開(kāi)發(fā)成員之一,今天我想通過(guò)本文,給大家介紹一下我們平時(shí)購(gòu)物時(shí)最常使用到的功能之一,添加產(chǎn)品到購(gòu)物車的技術(shù)實(shí)現(xiàn)。

即使沒(méi)有多少 Angular 開(kāi)發(fā)經(jīng)驗(yàn)的前端程序員,閱讀本文之后,也能對(duì) Spartacus 電商網(wǎng)站添加商品到購(gòu)物車的功能實(shí)現(xiàn),有一個(gè)最基礎(chǔ)的了解。

我們將 Github 上 Spartacus 代碼倉(cāng)庫(kù)的代碼克隆到本地并運(yùn)行后,通過(guò) https://localhost:4299 可以訪問(wèn)電商頁(yè)面的 UI:

可以看到此時(shí)右上角紅色的購(gòu)物車圖標(biāo)顯示的數(shù)字為0,意思是當(dāng)前用戶 Jerry Wang,還沒(méi)有添加任意的商品到購(gòu)物車?yán)铩?/p>

我們隨便在店鋪上選擇一臺(tái)電子設(shè)備,進(jìn)入商品明細(xì)頁(yè)面,點(diǎn)擊 Add To Cart,將其添加到購(gòu)物車:

可以在上圖產(chǎn)品明細(xì)頁(yè)面的 url 里,找到其產(chǎn)品編號(hào)為 1377492.

點(diǎn)擊了 Add To Cart 后,在 Chrome 開(kāi)發(fā)者工具 network 標(biāo)簽頁(yè)里觀察到一個(gè) HTTP POST 請(qǐng)求:

上圖展示的該 POST 請(qǐng)求的負(fù)載里,包含 ID 為 1377492 的產(chǎn)品信息。這個(gè) HTTP POST 請(qǐng)求調(diào)用購(gòu)物車更新的 Restful API , 將客戶選中的產(chǎn)品添加到購(gòu)物車?yán)铩?/p>

該請(qǐng)求響應(yīng)字段的 statusCode 為 success,如下圖所示,說(shuō)明 API 調(diào)用成功。

添加成功的購(gòu)物車界面一覽:

店鋪管理員可以登錄電商后臺(tái)管理頁(yè)面,根據(jù)購(gòu)物車編號(hào) 2357 查到我剛剛添加了商品的購(gòu)物車:

下面介紹 Add To Cart 按鈕的前端實(shí)現(xiàn)細(xì)節(jié)。

使用 Chrome 開(kāi)發(fā)者工具,很快就能找到這個(gè)按鈕所在的 Angular Component 的 selector:cx-add-to-cart

進(jìn)而找到該 Component 的實(shí)現(xiàn):

從上圖代碼第 21 行可以看出,Add To Cart 按鈕本身的顯示條件,是這個(gè)產(chǎn)品必須有庫(kù)存。當(dāng)客戶輸入的購(gòu)買個(gè)數(shù)小于等于 0,或者大于最大庫(kù)存數(shù)時(shí),該按鈕會(huì)被禁用。

點(diǎn)擊該 button 之后,執(zhí)行什么邏輯呢?第 23 行該 button 元素的類型 type 字段的值為 submit,而這個(gè) button 標(biāo)簽,包裹在一個(gè) form 標(biāo)簽內(nèi)。

我們到該 Component 對(duì)應(yīng)的模板文件頭部查看,發(fā)現(xiàn)了 submit 事件的處理函數(shù)為 addToCart:

在 addToCart 內(nèi)部,添加商品到購(gòu)物車的執(zhí)行邏輯,投遞到了該 Component 注入的服務(wù)類,ActiveCartService 的 addEntry 方法。

最終,我們使用 NgRx 狀態(tài)管理框架,將添加購(gòu)物車這個(gè)動(dòng)作,抽象成一個(gè)名為 CartActions.CartAddEntry 的 Action 類,并通過(guò) NgRx Store 的 dispatch 方法投遞。

根據(jù) NgRx 的架構(gòu)圖,這些投遞出的 Action,最終會(huì)被 Effects 接收,后者會(huì)調(diào)用 Restful API 同后臺(tái)服務(wù)器通信。

下圖就是負(fù)責(zé)接收 CartActions.CartAddEntry 的 Effects 實(shí)現(xiàn),后者又會(huì)將這個(gè)添加購(gòu)物車請(qǐng)求,投遞給 CartEntryConnector.

Spartacus 與后臺(tái)服務(wù)器的交互設(shè)計(jì)如下圖所示:

Connector 會(huì)把添加購(gòu)物車的請(qǐng)求轉(zhuǎn)發(fā)給 Adapter(即下圖第18行的 this.adapter),由后者調(diào)用 HTTP Restful API.

然而,這個(gè) CartEntryAdapter 本身和其 add 方法,前面都加上了 abstract 關(guān)鍵字,那么具體的實(shí)現(xiàn)到底在哪里呢?

在對(duì)應(yīng)的 NgModule 定義里能找到答案:OccCartEntryAdapter 實(shí)現(xiàn)了這個(gè) abstract class.

最終,我們?cè)?OccCartEntryAdapter 的實(shí)現(xiàn)代碼里,發(fā)現(xiàn)這個(gè)類,從配置信息里讀取并生成后臺(tái)對(duì)應(yīng)的購(gòu)物車更新的 API endpoint,然后使用注入的 HttpClient 的 post 方法(下圖第35行代碼),根據(jù)生成的 endpoint 調(diào)用這個(gè) API,最終完成購(gòu)物車更新操作。

總結(jié)

本文通過(guò)一個(gè)最常用的添加商品到購(gòu)物車的例子,分析了 Spartacus 這款開(kāi)源電商店鋪應(yīng)用解決方案前端通過(guò) Restful API 調(diào)用的方式同后端交互的原理。

歡迎大家訪問(wèn) Spartacus 項(xiàng)目的 Github 主頁(yè), 試用這個(gè)應(yīng)用,并提出您的寶貴意見(jiàn)。

更多Jerry的原創(chuàng)文章,盡在:"汪子熙":