React事务的一些理解

栏目: IOS · Android · 发布时间: 5年前

内容简介:学习React有一段时间了,刚接触不久对于React神奇的操作很好奇,迫不及待看了源码看过几遍源码总是一知半解,最近有时间再次学习React的相关知识,比如根据维基百科的解释: 提供独立可靠的恢复机制,保证出错时数据的一致性,不同事务之间互相独立。事务一般在数据库中使用的比较多,能保证出错的时候进行rollbakc恢复。在React源码中作者给出了事务的一张明细图能够帮助较好的理解。React内部的事务分为三个阶段initialize, method以及close阶段,会在开始和结束时候分别遍历transa

学习React有一段时间了,刚接触不久对于React神奇的操作很好奇,迫不及待看了源码看过几遍源码总是一知半解,最近有时间再次学习React的相关知识,比如 setState , componentDidMount 等,意识到了之前被忽略提及的知识点,那就是React内部的事务,个人觉得事务很重要生命周期中的 componentWillMountcomponentDidMount , componentDidUpdate 以及在一些生命周期中进行setState出现的一些出乎自己认知的结果,都和事务有很大的关系。

何为事务?

根据维基百科的解释: 提供独立可靠的恢复机制,保证出错时数据的一致性,不同事务之间互相独立。

事务一般在数据库中使用的比较多,能保证出错的时候进行rollbakc恢复。在React源码中作者给出了事务的一张明细图能够帮助较好的理解。React内部的事务分为三个阶段initialize, method以及close阶段,会在开始和结束时候分别遍历transactionWrapper内部的所有初始化方法和close方法。

React事务的一些理解

有哪些事务?

React内部有个事务对象,能够适配不同类型的事务:

Transaction.perform.call(this, this.reconcileTransaction.perform, this.reconcileTransaction, method, scope, a)

主要先介绍2种事务,分别对应虚拟生命周期事务,状态更新时的事务

批量更新事务(ReactDefaultBatchingStrategyTransaction)

React事务的一些理解

初始化进行组件挂载的时候会进行批量更新,批量更新方法会将ReactDefaultBatchingStrategy对象中的isBatchingUpdates设置为true,这也将导致后续加入的setState只会加入 dirtyComponents 中,在最后事务close的时候进行状态合并,这也解释了为何在componentDidMount中写多个setState,最后输出的状态不是意料值。

var ReactDefaultBatchingStrategy = {
  isBatchingUpdates: false,

  /**
   * Call the provided function in a context within which calls to `setState`
   * and friends are batched such that components aren't updated unnecessarily.
   */
  batchedUpdates: function (callback, a, b, c, d, e) {
    var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;

    ReactDefaultBatchingStrategy.isBatchingUpdates = true;

    // The code is written this way to avoid extra allocations
    if (alreadyBatchingUpdates) {
      return callback(a, b, c, d, e);
    } else {
      return transaction.perform(callback, null, a, b, c, d, e);
    }
  }
};
// 将新的partialState加入到_pendingStateQueue以后的组件加到dirtyComponents
function enqueueUpdate(component) {
  ensureInjected();
  if (!batchingStrategy.isBatchingUpdates) {
    batchingStrategy.batchedUpdates(enqueueUpdate, component);
    return;
  }

  dirtyComponents.push(component);
  if (component._updateBatchNumber == null) {
    component._updateBatchNumber = updateBatchNumber + 1;
  }
}

首先是初始化遍历执行emptyFunction,然后执行内部的被包装的方法,这里是 batchedMountComponentIntoNode ,顾名思义这个就是将虚拟DOM插入到真实节点下的方法,具体方法涉及到类别办法,不同实例化的组件类型,递归插入等等不在本章的讨论范围,不过有一点需要注意的是在这个方法内部进行已新事物,我称之为 生命周期事务 (ReactReconcileTransaction)。在最后close的阶段会将 isBatchingUpdates 设置为flase,以及调用 flushBatchedUpdates 方法进行将至更新。

var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];

var RESET_BATCHED_UPDATES = {
  initialize: emptyFunction,
  close: function () {
    ReactDefaultBatchingStrategy.isBatchingUpdates = false;
  }
};

var FLUSH_BATCHED_UPDATES = {
  initialize: emptyFunction,
  close: ReactUpdates.flushBatchedUpdates.bind(ReactUpdates)
};

更新事务(ReactUpdateFlushTransaction)

而上述说到的flushBatchedUpdates方法内部再次调用了一个新事务

React事务的一些理解

该事物我称之为更新事务,主要和setState有关,过程中会调用runBatchedUpdates, 将callBack函数加入到队列中,并将_pendingCallbacks的引用清空,关闭的时候的close方法主要是对dirtyComponents清空以及setState中回调函数的通知

React事务的一些理解

var TRANSACTION_WRAPPERS = [NESTED_UPDATES, UPDATE_QUEUEING];

var NESTED_UPDATES = {
  initialize: function () {
    this.dirtyComponentsLength = dirtyComponents.length;
  },
  close: function () {
    if (this.dirtyComponentsLength !== dirtyComponents.length) {
      dirtyComponents.splice(0, this.dirtyComponentsLength);
      flushBatchedUpdates();
    } else {
      dirtyComponents.length = 0;
    }
  }
};

var UPDATE_QUEUEING = {
  initialize: function () {
    this.callbackQueue.reset();
  },
  close: function () {
    this.callbackQueue.notifyAll();
  }
};

生命周期事务(ReactReconcileTransaction)

React事务的一些理解

if (inst.componentDidMount) {
  if ("development" !== 'production') {
    transaction.getReactMountReady().enqueue(function () {
      measureLifeCyclePerf(function () {
        return inst.componentDidMount();
      }, _this._debugID, 'componentDidMount');
    });
  } else {
    transaction.getReactMountReady().enqueue(inst.componentDidMount, inst);
  }
}

在这里开启了一个事务,componentDidMount被放入了callbacks队列中,当生命周期结束的时候会遍历事务中的close方法,其中就有notifyAll方法遍历callbacks进行输出,而这里的callback方法即为 componentDidMount 或者 componentDidUpdate

React事务的一些理解

var TRANSACTION_WRAPPERS = [SELECTION_RESTORATION, EVENT_SUPPRESSION, ON_DOM_READY_QUEUEING];
var EVENT_SUPPRESSION = {
  initialize: function () {
    var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();
    ReactBrowserEventEmitter.setEnabled(false);
    return currentlyEnabled;
  },

  // restores the previous value.
  close: function (previouslyEnabled) {
    ReactBrowserEventEmitter.setEnabled(previouslyEnabled);
  }
};

/**
 * Provides a queue for collecting `componentDidMount` and
 * `componentDidUpdate` callbacks during the transaction.
 */
var ON_DOM_READY_QUEUEING = {
  /**
   * Initializes the internal `onDOMReady` queue.
   */
  initialize: function () {
    this.reactMountReady.reset();
  },

  /**
   * After DOM is flushed, invoke all registered `onDOMReady` callbacks.
   */
  close: function () {
    this.reactMountReady.notifyAll();
  }
};

if ("development" !== 'production') {
  TRANSACTION_WRAPPERS.push({
    initialize: ReactInstrumentation.debugTool.onBeginFlush,
    close: ReactInstrumentation.debugTool.onEndFlush
  });
}

总结

React事务的一些理解

总之,React真的每次看都会为内部的实现所惊叹,虽然是前端的一种框架,但还是感觉能学到很多思想和知识,写的不对的地方还希望得到大牛们的指正。


以上所述就是小编给大家介绍的《React事务的一些理解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

跨越鸿沟

跨越鸿沟

[美] 杰弗里·摩尔(Geoffrey A. Moore) / 赵娅 / 机械工业出版社 / 2009-1 / 36.00元

在真正涉足高科技领域之前,你有必要读一读这本书——在这个节奏飞快、竞争激烈的技术竞技场上,这本书绝对能够帮助你更容易地获得成功。 ——威廉姆·劳森 罗盛软件公司董事会主席兼CEO 最近40年来,本书对高科技营销各个方面所做出的贡献远远超过了其他任何相关书籍。如今已经有无数企业和大学分别在自己的运营和教学过程中引入了鸿沟思想,如果你还不是这些企业或大学中的一员,你可能就要担心自己的未来了......一起来看看 《跨越鸿沟》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具