(精华2020年5月27日更新) react基础篇 setstate原理详解

先上张图
在这里插入图片描述
代码

// partialState 部分state
ReactComponent.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 batchedUpdates
let 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());
    }
}
// 面向切片编程 AOP
let 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 `<button οnclick="trigger(event,'add')">
            ${this.props.name}:${this.state.number}
            </button>`;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_41181778/article/details/106393416