成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

React 源碼深度解讀(八):事務(wù) - Part 2

airborne007 / 1310人閱讀

摘要:前言是一個(gè)十分龐大的庫,由于要同時(shí)考慮和,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)非常深,閱讀其源碼是一個(gè)非常艱辛的過程。在學(xué)習(xí)源碼的過程中,給我?guī)椭畲蟮木褪沁@個(gè)系列文章,于是決定基于這個(gè)系列文章談一下自己的理解。

前言

React 是一個(gè)十分龐大的庫,由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)非常深,閱讀其源碼是一個(gè)非常艱辛的過程。在學(xué)習(xí) React 源碼的過程中,給我?guī)椭畲蟮木褪沁@個(gè)系列文章,于是決定基于這個(gè)系列文章談一下自己的理解。本文會(huì)大量用到原文中的例子,想體會(huì)原汁原味的感覺,推薦閱讀原文。

本系列文章基于 React 15.4.2 ,以下是本系列其它文章的傳送門:
React 源碼深度解讀(一):首次 DOM 元素渲染 - Part 1
React 源碼深度解讀(二):首次 DOM 元素渲染 - Part 2
React 源碼深度解讀(三):首次 DOM 元素渲染 - Part 3
React 源碼深度解讀(四):首次自定義組件渲染 - Part 1
React 源碼深度解讀(五):首次自定義組件渲染 - Part 2
React 源碼深度解讀(六):依賴注入
React 源碼深度解讀(七):事務(wù) - Part 1
React 源碼深度解讀(八):事務(wù) - Part 2
React 源碼深度解讀(九):?jiǎn)蝹€(gè)元素更新
React 源碼深度解讀(十):Diff 算法詳解

正文

上一篇文章介紹了 transaction 的基本概念和用法。今天我們將講解在更新過程中,React 是如何通過多個(gè) transacion 之間的協(xié)作,來有效組織代碼的。

二、ReactUpdatesFlushTransaction

前文講到ReactDefaultBatchingStrategy close 的時(shí)候,會(huì)調(diào)用ReactUpdates.flushBatchedUpdates

PooledClass.addPoolingTo(ReactUpdatesFlushTransaction);

var flushBatchedUpdates = function () {
    while (dirtyComponents.length || asapEnqueued) {
        if (dirtyComponents.length) {
            var transaction = ReactUpdatesFlushTransaction.getPooled();
            transaction.perform(runBatchedUpdates, null, transaction);
            ReactUpdatesFlushTransaction.release(transaction);
        }

        if (asapEnqueued) {
            asapEnqueued = false;
            var queue = asapCallbackQueue;
            asapCallbackQueue = CallbackQueue.getPooled();
            queue.notifyAll();
            CallbackQueue.release(queue);
        }
    }
};

這里又調(diào)用了另一個(gè) transaction 來處理后續(xù)的流程,有所不同的是 transaction 的創(chuàng)建不是直接 new,而是調(diào)用getPooled方法。這個(gè)方法是通過前面的PooledClass.addPoolingTo注入到ReactUpdatesFlushTransaction中的,如果對(duì)這個(gè)步驟感興趣可以看看這篇文章。下面來看ReactUpdatesFlushTransaction的內(nèi)容:

Object.assign(
    ReactUpdatesFlushTransaction.prototype,
    Transaction, 
    {
        getTransactionWrappers: function () {
            return TRANSACTION_WRAPPERS;
        },

        destructor: function () {
            this.dirtyComponentsLength = null;
            CallbackQueue.release(this.callbackQueue);
            this.callbackQueue = null;
            ReactUpdates.ReactReconcileTransaction.release(this.reconcileTransaction);
            this.reconcileTransaction = null;
        },

        perform: function (method, scope, a) {
            return Transaction.perform.call(
                this,
                this.reconcileTransaction.perform,
                this.reconcileTransaction,
                method,
                scope,
                a
            );
        },
    }
);

var TRANSACTION_WRAPPERS = [NESTED_UPDATES, UPDATE_QUEUEING];

var NESTED_UPDATES = {
    initialize: function () {
        this.dirtyComponentsLength = dirtyComponents.length;
    },
    close: function () {
        if (this.dirtyComponentsLength !== dirtyComponents.length) {
            // Additional updates were enqueued by componentDidUpdate handlers or
            // similar; before our own UPDATE_QUEUEING wrapper closes, we want to run
            // these new updates so that if A"s componentDidUpdate calls setState on
            // B, B will update before the callback A"s updater provided when calling
            // setState.
            dirtyComponents.splice(0, this.dirtyComponentsLength);
            flushBatchedUpdates();
        } else {
            dirtyComponents.length = 0;
        }
    },
};

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

ReactUpdatesFlushTransaction覆蓋了原型鏈上的perform方法,不是直接調(diào)用 callback,而是嵌套調(diào)用了this.reconcileTransaction.perform,在將 callback 透?jìng)鹘oreconcileTransactionperform。這里的reconcileTransaction也開啟了實(shí)例池。

這里要注意下NESTED_UPDATES這個(gè) wrapper,如果dirtyComponents的數(shù)量跟 transaction 開始的時(shí)候不一樣,它又會(huì)遞歸調(diào)用flushBatchedUpdates,直到dirtyComponents不再變化為止。UPDATE_QUEUEING這個(gè) wrapper 暫時(shí)先忽略。

目前為止的調(diào)用關(guān)系如下:

三、ReactReconcileTransaction

ReactReconcileTransaction是一個(gè)普通的 transaction,定義了一些 DOM 操作相關(guān)的 wrapper:

function ReactReconcileTransaction(useCreateElement: boolean) {
  this.reinitializeTransaction();
  this.renderToStaticMarkup = false;
  this.reactMountReady = CallbackQueue.getPooled(null);
  this.useCreateElement = useCreateElement;
}

var Mixin = {
  getTransactionWrappers: function() {
    return TRANSACTION_WRAPPERS;
  },

  ...

  destructor: function() {
    CallbackQueue.release(this.reactMountReady);
    this.reactMountReady = null;
  },
};


Object.assign(ReactReconcileTransaction.prototype, Transaction, Mixin);

PooledClass.addPoolingTo(ReactReconcileTransaction);

var TRANSACTION_WRAPPERS = [
  SELECTION_RESTORATION,
  EVENT_SUPPRESSION,
  ON_DOM_READY_QUEUEING,
];

var SELECTION_RESTORATION = {
  /**
   * @return {Selection} Selection information.
   */
  initialize: ReactInputSelection.getSelectionInformation,
  /**
   * @param {Selection} sel Selection information returned from `initialize`.
   */
  close: ReactInputSelection.restoreSelection,
};

/**
 * Suppresses events (blur/focus) that could be inadvertently dispatched due to
 * high level DOM manipulations (like temporarily removing a text input from the
 * DOM).
 */
var EVENT_SUPPRESSION = {
  /**
   * @return {boolean} The enabled status of `ReactBrowserEventEmitter` before
   * the reconciliation.
   */
  initialize: function() {
    var currentlyEnabled = ReactBrowserEventEmitter.isEnabled();
    ReactBrowserEventEmitter.setEnabled(false);
    return currentlyEnabled;
  },

  /**
   * @param {boolean} previouslyEnabled Enabled status of
   *   `ReactBrowserEventEmitter` before the reconciliation occurred. `close`
   *   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();
  },
};

這三個(gè) wrapper 的作用注釋都講得很清楚了,不再贅述。值得一提的是這里perform的 callback 是ReactUpdatesFlushTransaction透?jìng)鬟^來的ReactUpdate.runBatchedUpdates

目前為止的調(diào)用關(guān)系如下:

四、總結(jié)

到此為止,transaction 相關(guān)的內(nèi)容就講完了,下一篇開始介紹真正的更新操作。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/99092.html

相關(guān)文章

  • React 源碼深度解讀(三):首次 DOM 元素渲染 - Part 3

    摘要:在學(xué)習(xí)源碼的過程中,給我?guī)椭畲蟮木褪沁@個(gè)系列文章,于是決定基于這個(gè)系列文章談一下自己的理解。到此為止,首次渲染就完成啦總結(jié)從啟動(dòng)到元素渲染到頁面,并不像看起來這么簡(jiǎn)單,中間經(jīng)歷了復(fù)雜的層級(jí)調(diào)用。 前言 React 是一個(gè)十分龐大的庫,由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)非常深,閱讀其源碼是一個(gè)非常艱辛的過...

    U2FsdGVkX1x 評(píng)論0 收藏0
  • React 源碼深度解讀(四):首次自定義組件渲染 - Part 1

    摘要:本篇開始介紹自定義組件是如何渲染的。組件將自定義組件命名為,結(jié)構(gòu)如下經(jīng)過編譯后,生成如下代碼構(gòu)建頂層包裝組件跟普通元素渲染一樣,第一步先會(huì)執(zhí)行創(chuàng)建為的。調(diào)用順序已在代碼中注釋。先看圖,這部分內(nèi)容將在下回分解 前言 React 是一個(gè)十分龐大的庫,由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)非常深,閱讀其源碼是一個(gè)非...

    Warren 評(píng)論0 收藏0
  • React 源碼深度解讀(六):依賴注入

    摘要:依賴注入和控制反轉(zhuǎn),這兩個(gè)詞經(jīng)常一起出現(xiàn)。一句話表述他們之間的關(guān)系依賴注入是控制反轉(zhuǎn)的一種實(shí)現(xiàn)方式。而兩者有大量的代碼都是可以共享的,這就是依賴注入的使用場(chǎng)景了。下一步就是創(chuàng)建具體的依賴內(nèi)容,然后注入到需要的地方這里的等于這個(gè)對(duì)象。 前言 React 是一個(gè)十分龐大的庫,由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)...

    glumes 評(píng)論0 收藏0
  • React 源碼深度解讀(七):事務(wù) - Part 1

    摘要:在學(xué)習(xí)源碼的過程中,給我?guī)椭畲蟮木褪沁@個(gè)系列文章,于是決定基于這個(gè)系列文章談一下自己的理解。說明就算拋出了錯(cuò)誤,部分的代碼也要繼續(xù)執(zhí)行,隨后再將錯(cuò)誤往上層代碼拋。和都能保證其中一個(gè)成員拋出錯(cuò)誤的時(shí)候,余下的能繼續(xù)執(zhí)行。 前言 React 是一個(gè)十分龐大的庫,由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)非常深,閱讀...

    KavenFan 評(píng)論0 收藏0
  • React 源碼深度解讀(二):首次 DOM 元素渲染 - Part 2

    摘要:本文將要講解的調(diào)用棧是下面這個(gè)樣子的平臺(tái)無關(guān)相關(guān)如果看源碼,我們會(huì)留意到很多相關(guān)的代碼,我們暫時(shí)先將其忽略,會(huì)在后續(xù)的文章中進(jìn)行講解。現(xiàn)在我們來看一下各實(shí)例間的關(guān)系目前為止的調(diào)用棧平臺(tái)無關(guān)相關(guān)下一篇講解三總結(jié)本文講解了轉(zhuǎn)化為的過程。 歡迎關(guān)注我的公眾號(hào)睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言 R...

    wean 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<