Preact是React的輕量級實現,是React比較好的替代者之一,有着體積小的優勢,固然與React之間必定會存在實現上的差別,本文介紹了在 setState 方面的差別之處。react
首先來分析下React以及Preact在setState部分的具體實現。antd
(太長不看想偷懶,能夠直接下翻看結論)函數
關鍵代碼:源碼分析
// ReactUpdateQueue.js enqueueSetState: function(publicInstance, partialState) { ... var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []); queue.push(partialState); enqueueUpdate(internalInstance); }
能夠看到React在 setState 的時候不會作任何處理,會把變動直接放到一個專門處理 state 的隊列裏供組件更新時使用。性能
// ReactCompositeComponent.js updateComponent: function( transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext, ) { var inst = this._instance; ... var willReceive = false; var nextContext; if (this._context === nextUnmaskedContext) { nextContext = inst.context; } else { nextContext = this._processContext(nextUnmaskedContext); willReceive = true; } var prevProps = prevParentElement.props; var nextProps = nextParentElement.props; if (prevParentElement !== nextParentElement) { willReceive = true; } if (willReceive && inst.componentWillReceiveProps) { ... inst.componentWillReceiveProps(nextProps, nextContext); } // 在此處才計算 nextState var nextState = this._processPendingState(nextProps, nextContext); // 此處傳入了 nextProps var shouldUpdate = true; if (!this._pendingForceUpdate) { if (inst.shouldComponentUpdate) { ... shouldUpdate = inst.shouldComponentUpdate( nextProps, nextState, nextContext, ); } else { if (this._compositeType === CompositeTypes.PureClass) { // 敲黑板,知識點 —— 若是你的組件沒實現shouldComponentUpdate,那麼把React.Component 換成 React.PureComponent 能夠得到基礎版優化,提升性能。 shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState); // 淺比較,能夠抄去本身改爲屬性黑/白名單版 } } } ... } // ReactCompositeComponent.js _processPendingState: function(props, context) { // props: nextProps var inst = this._instance; var queue = this._pendingStateQueue; var replace = this._pendingReplaceState; this._pendingReplaceState = false; this._pendingStateQueue = null; if (!queue) { return inst.state; } if (replace && queue.length === 1) { return queue[0]; } var nextState = Object.assign({}, replace ? queue[0] : inst.state); for (var i = replace ? 1 : 0; i < queue.length; i++) { var partial = queue[i]; Object.assign( nextState, typeof partial === 'function' ? partial.call(inst, nextState, props, context) // nextProps : partial, ); } return nextState; }
經過上面組件更新的流程代碼能夠看到:優化
關鍵代碼:this
// component.js setState(state, callback) { let s = this.state; if (!this.prevState) this.prevState = extend({}, s); extend(s, typeof state==='function' ? state(s, this.props) : state); if (callback) (this._renderCallbacks = (this._renderCallbacks || [])).push(callback); enqueueRender(this); }
實現的簡單粗暴,在 setState 的時候就進行了合併,會當即改寫 this.state,在第一次 setState 時會保留 state 狀態到 prevState。因爲是當即合併state,若是入參state是函數,props 將只是當前 this.props。code
export function renderComponent(component, opts, mountAll, isChild) { ... previousProps = component.prevProps || props, previousState = component.prevState || state, previousContext = component.prevContext || context, ... // if updating if (isUpdate) { component.props = previousProps; component.state = previousState; component.context = previousContext; if (opts!==FORCE_RENDER && component.shouldComponentUpdate && component.shouldComponentUpdate(props, state, context) === false) { skip = true; } else if (component.componentWillUpdate) { component.componentWillUpdate(props, state, context); } component.props = props; component.state = state; component.context = context; } ... }
在更新流程前提取了舊 state,shouldComponentUpdate、componentWillUpdate 以後還原回新值,因此在 shouldComponentUpdate 生命週期中,this.props 將獲取的是 prevProps,這裏與 React 的邏輯並不一致。component
相同點:生命週期
不一樣點:
若是你寫的工程須要同時兼容React及Preact的話:
p.s: antd-mobile 2.0正式版已發佈,同時兼容react、preact,輕量、快速、易用的移動端組件庫,等你來用~ 【傳送門】