這段時間做的項目開發中用的是React+Redux+ImmutableJs+Es6開發,總結了immutable.js的相關使用姿勢:
Immutable Data 顧名思義是指一旦被創造后,就不可以被改變的數據。可以通過使用Immutable Data,可以讓我們更容易的去處理緩存、回退、數據變化檢測等問題,簡化我們的開發。
我們知道 react.js很著名的就是它處理dom的做法,它是通過Virtual Dom來查看diff,然后再改動需要改動的Dom。但是有個問題當state更新時,如果數據沒變,react也會去做Virtual Dom的diff,這就產生了浪費,其實這種情況其實很常見。
當然React 做性能優化時還有一個避免重復渲染的大招,就是使用生命周期 shouldComponentUpdate(),但它默認返回 true,即始終會執行 render() 方法,然后做 Virtual Dom 比較,並得出是否需要做真實 Dom 更新。
這個時候其實還有方案來解決這個問題,用PureRenderMixin,貌似也可以解決這個問題,在某些情況下進行性能加速。
import PureRenderMixin from 'react-addons-pure-render-mixin';
class FooComponent extends React.Component {
constructor(props) {
super(props);
this.shouldComponentUpdate =PureRenderMixin.shouldComponentUpdate.bind(this);
}
render() {
return <div className={this.props.className}>foo</div>;
}
}
其實就是, 實現了 shouldComponentUpdate, 它對當前及下一步的 props 和 state 進行比較,並當相等時返回 false,不進行渲染
看了下PureRenderMixin官方文檔,This only shallowly compares the objects,Only mix into components which have simple props and state。
PureRenderMixin,它只是簡單的淺比較,不適用於復雜的比較。
順着剛剛的這條思路走,我們可以在shouldComponentUpdate()內做判斷,如果有props/state有變化,那么再進行render(),這個時候的問題就來了,你如何做比較,shallowly compare,達不到效果,deep compare則性能很差
這個時候immutable.js來了,使用immutable.js可以解決這個問題。
首先Immutable.js的拷貝,是當對象樹中一個節點發生變化,只修改這個節點和受它影響的父節點,其它節點則進行共享。
import Immutable from 'immutable';
const initialState = Immutable.fromJS({ data: null });
當然可以用deep-copy做到這一點,但是差別在於性能。每次deep-copy都要把整個對象遞歸的復制一份。而Immutable的實現像鏈表,添加一個新結點把舊結點的父子關系轉移到新結點上。
生成immutable對象后,然后再在生命周期shouldComponentUpdate做做判斷
shouldComponentUpdate(nextProps) {
return !this.props.situation.equals(nextProps.situation);
}
對當前及下一步的 props 的immutable對象 進行比較,並當相等時返回 false,不進行渲染,只有為true的時候,才進行render()處理。
react+immutable這樣就可以大大提升react的性能。
