深耕業務——商品列表底部分銷商品資源廣告位
背景:有贊微商城後臺商品管理頁,底部增加供貨商品推薦資源位,根據不同的商家展示不同的商品!
作為深耕的業務,我們就從一個我遇到的複雜需求開始做個引子。栗子如下(可先看圖片過個眼癮):


需求列表如下
基本要求:
- 基本 UI 實現
- BlockHeder,點選換一批切換至下一頁,點選更多跳轉至分銷市場
- 商品卡片
- 曝光埋點資料:當商品底部出現使用者視口傳送曝光資料
- window resize 商品卡片資料適配
更高要求:
- 效能優化:resize 獲取資料減少 ajax 資料請求的次數;節流
- 資料快取:當
size
小於等於goodList.length
則不予以ajax
請求資料,減少不必要的頻寬 - 非正常分頁:更加不同的
size
獲取不同的資料,以及分頁 - 程式碼邏輯:VM 避免超級繁瑣,程式碼的邏輯和歸類清晰明瞭
- 低耦合:達到更鬆散的控制,對於以後的拆分和開發更加敏捷
- 錯誤隔離:當前分銷廣告位掛掉,不能影響到整個商品列表頁!
當大家看到產品的 PRD ,看了這個需求和要求之後,每個人根據自己的程式開發經驗和設計經驗上,每個人都能給出不同的解決方案。其實呢,每個解決方案都是一種方式,只是在不同的角度上實施以及設計的思維上不同。So,我想分享給大家的,也是經過我的思考後以及完善的一種解決方案,拿出來僅供參考。
到底什麼是業務
分享實施方案前,先討論一下到底什麼是業務;而程式設計師寫程式碼都是服務於業務的麼? 在老闆眼中,業務就是賺錢的工具;在銷售員眼中,業務就是必須完成的指標;在產品的眼中,業務就是需要實現完成的需求。。。每個人對業務的理解都不一樣,但是,有誰考慮過,在前端開發工程師眼中的業務到底是什麼??
下面是我站在前端的角度去理解業務,如下:

So,在我的理解裡,前端所寫的業務拆分成為6大部分:
- 業務資料:負責獲取業務資料
- 業務邏輯:實現產品所定義的規則
- 邏輯資料:通過一系列規則所產出的邏輯資料
- 檢視資料:通過邏輯資料轉換成檢視資料(不將邏輯和檢視直接繫結)
- 檢視展示:通過檢視資料,直接驅動檢視層展示對應檢視
- 檢視功能:通過檢視展示組裝成的需求功能
在簡單的業務需求中,可能我拿到的後端資料,就直接可以渲染檢視層,然後就完善功能。從開發的成本和複雜度考量上,是不值得去做業務拆分。所以,在複雜的業務需求中以及兼顧拆分和維護中,這種業務方法論就可以大展手腳了。以下就是我拿開頭的例子,詳細解析圍繞業務的 6 大部分的設計。
具體實現步驟
第一步:基本元件的劃分
結構劃分:本次元件劃分的規則是先上下、再左右、由外至內;劃分結果是
BackHeader

GoodsList

GoodsCard

功能劃分: 頂級容器:錯誤隔離,灰度控制,埋點資料及控制,ajax 請求。 檢視展示:分發資料,元件回撥
第二步:實施
:::info 提示:由 react16
提供 componentDidCatch
進行錯誤隔離,也可以使用 try...catch
實現錯誤隔離 :::
在 react
中,最核心、也就最靈活的處理檢視變化的方式呢,就將驅動檢視的資料做成可配的;所以第一步,根據結構的劃分,將需求做成資料的配置,程式碼如下:
render() { const { goodsList, pageIndex, size } = this.state; if (!goodsList.length) { return <div ref={node => this.fenxiaoRef = node} />; } return ( <div className="fenxiao-recommend " ref={node => this.fenxiaoRef = node}> <BlockHeader onGoodsChange={this.handlerClick} /> <GoodsListContainer size={size} pageIndex={pageIndex} goodsList={goodsList} /> </div> ); } 複製程式碼
頂級容器元件在 DidMount
時,做灰度控制, ajax
獲取資料驅動檢視。 BlockHeader
接收 props onGoodsChange
回撥,請求資料,再分發資料。
計算當前可展示的商品數量 size
;獲取頂層容器 ref
獲取容器獲取容器寬度。程式碼如下:
/** * 計算展示多少卡片 * 返回值 * size */ computedStyle = () => { const { fenxiaoRef } = this; if (!fenxiaoRef) { return; } const { width } = fenxiaoRef.getBoundingClientRect(); let size = Math.floor(width / 144); this.setState({ size }); } 複製程式碼
根據 size
獲取商品的個數 goodsList
,並監聽 window resize
;其中以下集中情況則不予以請求
size <= goodsList.length size

埋點資料:曝光 曝光埋點的基本需求是,當商品出現在瀏覽器的視口中後(即使用者的視口),傳送黃金令箭!曝光一個商品傳送一支令箭!
那麼問題來了,如何判斷當前分銷商品列表廣告位(分銷商品 DOM 元素)出現在使用者的視口呢?
我採用了一種比較 low
,也是最常規的解決方案:以瀏覽器視口左下角為原點座標,向上為正,向下為負; 獲取當前 DOM
距離頁面頂部的距離,即 const { top } = node.getBoundingClientRect()
,獲取視口高度 document.ocumentElement.clientHeight
;
// 以頁面右下角為原點,計算分銷商品是否 曝光 export function isExposure(node) { if (!node) { return null; } // 視口高度 const clientHeight = ddcocument.documentElement.clientHeight; const { top } = node.getBoundingClientRect(); return clientHeight > top; } 複製程式碼
