(精华)2020年7月31日 React setstate原理详解
发布日期:2021-06-29 15:08:34 浏览次数:3 分类:技术文章

本文共 7903 字,大约阅读时间需要 26 分钟。

在这里插入图片描述

// partialState 部分stateReactComponent.prototype.setState = function (partialState, callback) {
invariant( typeof partialState === 'object' || typeof partialState === 'function' || partialState == null, 'setState(...): takes an object of state variables to update or a ' + 'function which returns an object of state variables.', ); this.updater.enqueueSetState(this, partialState); if (callback) {
this.updater.enqueueCallback(this, callback, 'setState'); }};enqueueSetState: function (publicInstance, partialState) {
if (__DEV__) {
ReactInstrumentation.debugTool.onSetState(); warning( partialState != null, 'setState(...): You passed an undefined or null state object; ' + 'instead, use forceUpdate().', ); } var internalInstance = getInternalInstanceReadyForUpdate( publicInstance, 'setState', ); if (!internalInstance) {
return; } var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []); queue.push(partialState); enqueueUpdate(internalInstance);}// 通过enqueueUpdate执行state的更新function enqueueUpdate(component) {
ensureInjected(); // batchingStrategy批量更新的策略 // isBatchingUpdates是否处于批量更新 最开始是默认false if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component); return; } // 如果isBatchingUpdates为true的话 不进行state的更新操作 而是将需要更新的component添加到dirtyComponents数组中去 dirtyComponents.push(component); if (component._updateBatchNumber == null) {
component._updateBatchNumber = updateBatchNumber + 1; }}// _pendingStateQueue// 会调用updateComponent方法performUpdateIfNecessary: function (transaction) {
if (this._pendingElement != null) {
ReactReconciler.receiveComponent( this, this._pendingElement, transaction, this._context, ); } else if (this._pendingStateQueue !== null || this._pendingForceUpdate) {
this.updateComponent( transaction, this._currentElement, this._currentElement, this._context, this._context, ); } else {
this._updateBatchNumber = null; }}if (!batchingStrategy.isBatchingUpdates) {
batchingStrategy.batchedUpdates(enqueueUpdate, component); return;}dirtyComponents.push(component);if (component._updateBatchNumber == null) {
component._updateBatchNumber = updateBatchNumber + 1;}var ReactDefaultBatchingStrategy = {
isBatchingUpdates: false, batchedUpdates: function (callback, a, b, c, d, e) {
var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates; ReactDefaultBatchingStrategy.isBatchingUpdates = true; if (alreadyBatchingUpdates) {
return callback(a, b, c, d, e); } else {
return transaction.perform(callback, null, a, b, c, d, e); } }}{
// 会检测组件中的state和props是否发生变化,有变化才会进行更新; // 如果shouldUpdateComponent函数中返回false则不会执行组件的更新 updateComponent: function (transaction, prevParentElement, nextParentElement, prevUnmaskedContext, nextUnmaskedContext, ) {
var inst = this._instance; var nextState = this._processPendingState(nextProps, nextContext); var shouldUpdate = true; if (!this._pendingForceUpdate) {
if (inst.shouldComponentUpdate) {
if (__DEV__) {
shouldUpdate = measureLifeCyclePerf( () => inst.shouldComponentUpdate(nextProps, nextState, nextContext), this._debugID, 'shouldComponentUpdate', ); } else {
shouldUpdate = inst.shouldComponentUpdate( nextProps, nextState, nextContext, ); } } else {
if (this._compositeType === CompositeTypes.PureClass) {
shouldUpdate = !shallowEqual(prevProps, nextProps) || !shallowEqual(inst.state, nextState); } } } }, // 该方法会合并需要更新的state,然后加入到更新队列中 _processPendingState: function (props, context) {
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) : partial, ); } return nextState; }};

模拟实现

class Transaction {
constructor(wrappers) {
this.wrappers = wrappers;//{initialize,close} } perform(anyMethod) {
console.log("this.wrappers:", this.wrappers); this.wrappers.forEach(wrapper => wrapper.initialize()); anyMethod.call(); this.wrappers.forEach(wrapper => wrapper.close()); }}//batchingStrategy.isBatchingUpdates batchedUpdateslet batchingStrategy = {
isBatchingUpdates: false,//默认是非批量更新模式 dirtyComponents: [],// 脏组件 就组件的状态和界面上显示的不一样 batchedUpdates() {
this.dirtyComponents.forEach(component => component.updateComponent()); }}class Updater {
constructor(component) {
this.component = component; this.pendingStates = []; } addState(partcialState) {
this.pendingStates.push(partcialState); batchingStrategy.isBatchingUpdates ? batchingStrategy.dirtyComponents.push(this.component) : this.component.updateComponent() }}class Component {
constructor(props) {
this.props = props; this.$updater = new Updater(this); } setState(partcialState) {
this.$updater.addState(partcialState); } updateComponent() {
this.$updater.pendingStates.forEach(partcialState => Object.assign(this.state, partcialState)); this.$updater.pendingStates.length = 0; let oldElement = this.domElement; let newElement = this.createDOMFromDOMString(); oldElement.parentElement.replaceChild(newElement, oldElement); } //把一个DOM模板字符串转成真实的DOM元素 createDOMFromDOMString() {
//this; let htmlString = this.render(); let div = document.createElement('div'); div.innerHTML = htmlString; this.domElement = div.children[0]; //让这个BUTTONDOM节点的component属性等于当前Counter组建的实例 this.domElement.component = this; //this.domElement.addEventListener('click',this.add.bind(this)); return this.domElement; } mount(container) {
container.appendChild(this.createDOMFromDOMString()); }}// 面向切片编程 AOPlet transaction = new Transaction([ {
initialize() {
batchingStrategy.isBatchingUpdates = true;//开始批量更新模式 }, close() {
batchingStrategy.isBatchingUpdates = false; batchingStrategy.batchedUpdates();//进行批量更新,把所有的脏组件根据自己的状态和属性重新渲染 } }]);window.trigger = function (event, method) {
let component = event.target.component;//event.target=this.domElement transaction.perform(component[method].bind(component));}class Counter extends Component {
constructor(props) {
super(props); this.state = {
number: 0 } } add() {
this.setState({
number: this.state.number + 1 }); console.log(this.state);//0 this.setState({
number: this.state.number + 2 }); console.log(this.state);//0 setTimeout(() => {
this.setState({
number: this.state.number + 3 }); console.log(this.state);//5 this.setState({
number: this.state.number + 4 }); console.log(this.state);//9 }, 1000); } render() {
return ``; }}

转载地址:https://codeboy.blog.csdn.net/article/details/107704213 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:(精华)2020年7月31日 React 虚拟dom的渲染机制和性能调优
下一篇:(精华)2020年7月30日 微信小程序 内置插件的使用

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月15日 04时18分07秒