背景:有贊微商城後臺商品管理頁,底部增長供貨商品推薦資源位,根據不一樣的商家展現不一樣的商品!前端
做爲深耕的業務,咱們就從一個我遇到的複雜需求開始作個引子。栗子以下(可先看圖片過個眼癮):node
基本要求:react
更高要求:程序員
size
小於等於 goodList.length
則不予以 ajax
請求數據,減小沒必要要的帶寬size
獲取不一樣的數據,以及分頁當你們看到產品的 PRD ,看了這個需求和要求以後,每一個人根據本身的程序開發經驗和設計經驗上,每一個人都能給出不一樣的解決方案。其實呢,每一個解決方案都是一種方式,只是在不一樣的角度上實施以及設計的思惟上不一樣。So,我想分享給你們的,也是通過個人思考後以及完善的一種解決方案,拿出來僅供參考。ajax
分享實施方案前,先討論一下到底什麼是業務;而程序員寫代碼都是服務於業務的麼? 在老闆眼中,業務就是賺錢的工具;在銷售員眼中,業務就是必須完成的指標;在產品的眼中,業務就是須要實現完成的需求。。。每一個人對業務的理解都不同,可是,有誰考慮過,在前端開發工程師眼中的業務究竟是什麼??後端
下面是我站在前端的角度去理解業務,以下:瀏覽器
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;
}
複製代碼
「小公司寫代碼,大公司改代碼」好多年前就據說過這麼一句話,可是做爲程序猿來講,最大的痛點就是:別人不寫文檔,別人不寫註釋,以及寫文檔,寫註釋!因此在原有系統的維護當中,盡最大可能作到: