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,轻量、快速、易用的移动端组件库,等你来用~ 【传送门】