// partialState partialState
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);
}

// Update state via enqueueUpdate
function enqueueUpdate(component) {
  ensureInjected();
  // batchingStrategy Batch update strategy
  // Whether isBatchingUpdates start with batch updates is false by default
  if(! batchingStrategy.isBatchingUpdates) { batchingStrategy.batchedUpdates(enqueueUpdate, component);return;
  }
  // If isBatchingUpdates are true, state is not updated; instead, the component to be updated is added to the dirtyComponents array
  dirtyComponents.push(component);
  if (component._updateBatchNumber == null) {
    component._updateBatchNumber = updateBatchNumber + 1; }}// _pendingStateQueue
// The updateComponent method is called
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); }}} {// Check whether the props and state of the component are changed.
  // If the function shouldUpdateComponent returns false then the component update is not performed
  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); }}}},// This method consolidates the states that need to be updated and adds them to the update queue
  _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,
      );
    }

    returnnextState; }};Copy the code

Analog implementation

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.// The default mode is non-batch update
    dirtyComponents: [].// The state of the dirty component is different from that displayed on the interface
    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);
    }
    // Convert a DOM template string into a real DOM element
    createDOMFromDOMString() {
        //this;
        let htmlString = this.render();
        let div = document.createElement('div');
        div.innerHTML = htmlString;
        this.domElement = div.children[0];
        // Make the Component property of the BUTTONDOM node equal to the instance of the current Counter component
        this.domElement.component = this;
        //this.domElement.addEventListener('click',this.add.bind(this));
        return this.domElement;
    }
    mount(container) {
        container.appendChild(this.createDOMFromDOMString()); }}Slice-oriented programming AOP
let transaction = new Transaction([
    {
        initialize() {
            batchingStrategy.isBatchingUpdates = true;// Start batch update mode
        },
        close() {
            batchingStrategy.isBatchingUpdates = false;
            batchingStrategy.batchedUpdates();// Perform batch updates to re-render all dirty components according to their state and properties}}]);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 &western nclick = "trigger (event, 'add')" >The ${this.props.name}:The ${this.state.number}
            </button>`; }}Copy the code