内部小组分享底稿.
经过判断减小数据变化触发的从新渲染, 以及以后的 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... .