目前電商領域有兩款比較出名的開源電商網站解決方案,分別是基于 Angular 開發框架,代號為 Spartacus 的開源項目,以及基于 Vue 的 Vue Storefront.


作為 Spartacus 開源項目的開發成員之一,今天我想通過本文,給大家介紹一下我們平時購物時最常使用到的功能之一,添加產品到購物車的技術實現。

即使沒有多少 Angular 開發經驗的前端程序員,閱讀本文之后,也能對 Spartacus 電商網站添加商品到購物車的功能實現,有一個最基礎的了解。

我們將 Github 上 Spartacus 代碼倉庫的代碼克隆到本地并運行后,通過 https://localhost:4299 可以訪問電商頁面的 UI:

可以看到此時右上角紅色的購物車圖標顯示的數字為0,意思是當前用戶 Jerry Wang,還沒有添加任意的商品到購物車里。

我們隨便在店鋪上選擇一臺電子設備,進入商品明細頁面,點擊 Add To Cart,將其添加到購物車:

可以在上圖產品明細頁面的 url 里,找到其產品編號為 1377492.

點擊了 Add To Cart 后,在 Chrome 開發者工具 network 標簽頁里觀察到一個 HTTP POST 請求:

上圖展示的該 POST 請求的負載里,包含 ID 為 1377492 的產品信息。這個 HTTP POST 請求調用購物車更新的 Restful API , 將客戶選中的產品添加到購物車里。

該請求響應字段的 statusCode 為 success,如下圖所示,說明 API 調用成功。

添加成功的購物車界面一覽:

店鋪管理員可以登錄電商后臺管理頁面,根據購物車編號 2357 查到我剛剛添加了商品的購物車:

下面介紹 Add To Cart 按鈕的前端實現細節。

使用 Chrome 開發者工具,很快就能找到這個按鈕所在的 Angular Component 的 selector:cx-add-to-cart

進而找到該 Component 的實現:

從上圖代碼第 21 行可以看出,Add To Cart 按鈕本身的顯示條件,是這個產品必須有庫存。當客戶輸入的購買個數小于等于 0,或者大于最大庫存數時,該按鈕會被禁用。

點擊該 button 之后,執行什么邏輯呢?第 23 行該 button 元素的類型 type 字段的值為 submit,而這個 button 標簽,包裹在一個 form 標簽內。

我們到該 Component 對應的模板文件頭部查看,發現了 submit 事件的處理函數為 addToCart:

在 addToCart 內部,添加商品到購物車的執行邏輯,投遞到了該 Component 注入的服務類,ActiveCartService 的 addEntry 方法。

最終,我們使用 NgRx 狀態管理框架,將添加購物車這個動作,抽象成一個名為 CartActions.CartAddEntry 的 Action 類,并通過 NgRx Store 的 dispatch 方法投遞。

根據 NgRx 的架構圖,這些投遞出的 Action,最終會被 Effects 接收,后者會調用 Restful API 同后臺服務器通信。

下圖就是負責接收 CartActions.CartAddEntry 的 Effects 實現,后者又會將這個添加購物車請求,投遞給 CartEntryConnector.

Spartacus 與后臺服務器的交互設計如下圖所示:

Connector 會把添加購物車的請求轉發給 Adapter(即下圖第18行的 this.adapter),由后者調用 HTTP Restful API.

然而,這個 CartEntryAdapter 本身和其 add 方法,前面都加上了 abstract 關鍵字,那么具體的實現到底在哪里呢?

在對應的 NgModule 定義里能找到答案:OccCartEntryAdapter 實現了這個 abstract class.

最終,我們在 OccCartEntryAdapter 的實現代碼里,發現這個類,從配置信息里讀取并生成后臺對應的購物車更新的 API endpoint,然后使用注入的 HttpClient 的 post 方法(下圖第35行代碼),根據生成的 endpoint 調用這個 API,最終完成購物車更新操作。

總結

本文通過一個最常用的添加商品到購物車的例子,分析了 Spartacus 這款開源電商店鋪應用解決方案前端通過 Restful API 調用的方式同后端交互的原理。

歡迎大家訪問 Spartacus 項目的 Github 主頁, 試用這個應用,并提出您的寶貴意見。

更多Jerry的原創文章,盡在:"汪子熙":