內部小組分享底稿.
經過判斷減小數據變化觸發的從新渲染, 以及以後的 DOM diffhtml
shouldComponentUpdate(nextProps, nextState) { if (this.props.color !== nextProps.color) { return true; } if (this.state.count !== nextState.count) { return true; } return false; }
函數式語言當中, 語言設計容許兩個對象同樣, 舉例 Clojure:前端
(= {:a 1} {:a 1}) ; true (identical? {:a 1} {:a 1}) ; false
遞歸匹配, 性能並不高.react
JavaScript 對象基於引用傳值, 比較單一git
{a: 1} === {a: 1} // false
大致方案, 經過手動維護, 讓相同的數據儘可能保證引用一致, 控制性能.github
function updateColorMap(colormap) { return {...colormap, right: 'blue'}; }
每一個函數體當中生成的對象都會有新的引用, useMemo
能夠保留一致的引用.web
const myObject = useMemo(() => ({ key: "value" }), [])
注意: 用花括號直接寫對象基本上就是新的引用了,chrome
{} {a: 1} {...obj}
通常組件內部不變的對象, 都是從 state, ref, 再或者組件外全局有一個引用.json
判斷參數是否改變, 若是沒有改變, 就直接複用已有的組件, 不從新生成:瀏覽器
const MyComponent = React.memo(function MyComponent(props) { /* only rerenders if props change */ });
React.memo
有第二個參數, 用於自定義判斷的規則:性能優化
const MemoItem = React.memo(Item, (prevProps, nextProps) => { if (prevProps.item.selected === nextProps.item.selected) { return true; } return false; });
使用 React.memo
包裹組件:
let Inner: FC<{ onClick: () => void }> = React.memo((props) => { return <div> <span>inner</span> </div>; });
使用 useCallback
let Outer: FC<{}> = React.memo((props) => { const [counter, setCounter] = useState(0); const onClick = useCallback(()=>{ setCounter(prevState => ++prevState) },[]); return <div> <span>outer: {counter}</span> <Inner onClick={onClick} /> </div>; });
let NewComponent: FC<{}> = React.memo((props) => { let elRef = useRef<HTMLDivElement>() // 錯誤寫法 if (elRef.current) { elRef.current.style.color = 'red' } return <div ref={elRef}></div>; });
DOM 發生改變的時候, 通常會有比較多後續的佈局和 compose 計算去繪製新的界面.
特別是在腳本執行過程中發生的話, 會對性能有明顯影響.
腳本執行完再執行, 讓瀏覽器自動處理(合併, 避免頻繁 DOM 操做).
let a = {} let b = produce(a, draft => { draft.b = 1 }) a === b // false
若是數據不發生改變, 直接用原始數據.
(Hooks API 以後, 數據被拆散了, 能夠減小 immer 的使用.)
class 組件, 高階組件當中自動作了基礎的優化.
shouldComponentUpdate(nextProps: IRexDataLayerProps, nextState: any) { if (!shallowequal(nextProps.parentProps, this.props.parentProps)) return true; if (!shallowequal(nextProps.computedProps, this.props.computedProps)) return true; return false; }
Hook API, 沒有中間一層組件, 直接觸發當前組件更新, 存在性能問題.(還要考慮優化方案)
let contextData = useRexContext((store: IGlobalStore) => { return { data: store.data, homeData: store.homeData, }; });
業務當中通常能夠接受, 由於數據一般都是在更新的. 新能敏感場景須要額外考慮.
/home/plant/123/shop/456/789
解析爲
{ "raw": "home", "name": "home", "matches": true, "restPath": ["plant", "123", "shop", "456", "789"], "params": {}, "data": {}, "next": { "raw": "plant/:plantId", "name": "plant", "matches": true, "restPath": ["shop", "456", "789"], "params": { "plantId": "123" }, "data": { "plantId": "123" }, "next": { "raw": "shop/:shopId/:corner", "name": "shop", "matches": true, "next": null, "restPath": [], "data": { "shopId": "456", "corner": "789" }, "params": { "plantId": "123", "shopId": "456", "corner": "789" } } } }
生成對象保存起來, 路由發生變動時再從新解析. 這樣對象引用通常保持一致.
DevTools
https://developers.google.com...
React DevTools
https://www.debugbear.com/blo...
官方推薦性能優化方案...
https://reactjs.org/docs/opti...
樹形組件: 隱藏子樹, 定製減小更新. (我的建議看狀況本身實現, 通用組件通常都很差優化).
略
useMemo
略
Dropdown 的替換, 老版本 antd 的 bug(升級 rc-select@9.0.3
).
略
https://github.com/react-comp...
其餘關於積夢前端的模塊和工具能夠查看咱們的 GitHub 主頁 https://github.com/jimengio .
目前團隊正在擴充, 招聘文檔見 GitHub 倉庫 https://github.com/jimengio/h... .