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

資訊專欄INFORMATION COLUMN

揭密React setState

JeOam / 2749人閱讀

摘要:下面來(lái)逐步的解析圖里的流程。一將事務(wù)放進(jìn)隊(duì)列中這里的可以傳也可以傳它會(huì)產(chǎn)生新的以一種的方式跟舊的進(jìn)行合并。如果當(dāng)前不在更新過(guò)程的話,則執(zhí)行更新事務(wù)。以上即為的實(shí)現(xiàn)過(guò)程,最后還是用一個(gè)流程圖在做一個(gè)總結(jié)吧參考文檔

前言

學(xué)過(guò)react的人都知道,setState在react里是一個(gè)很重要的方法,使用它可以更新我們數(shù)據(jù)的狀態(tài),本篇文章從簡(jiǎn)單使用深入到setState的內(nèi)部,全方位為你揭開(kāi)setState的神秘面紗~

setState的使用注意事項(xiàng)

setState(updater, callback)這個(gè)方法是用來(lái)告訴react組件數(shù)據(jù)有更新,有可能需要重新渲染。它是異步的,react通常會(huì)集齊一批需要更新的組件,然后一次性更新來(lái)保證渲染的性能,所以這就給我們埋了一個(gè)坑:

那就是在使用setState改變狀態(tài)之后,立刻通過(guò)this.state去拿最新的狀態(tài)往往是拿不到的。

要點(diǎn)一

所以第一個(gè)使用要點(diǎn)就是:如果你需要基于最新的state做業(yè)務(wù)的話,可以在componentDidUpdate或者setState的回調(diào)函數(shù)里獲取。(注:官方推薦第一種做法)

// setState回調(diào)函數(shù)
changeTitle: function (event) {
  this.setState({ title: event.target.value }, () => this.APICallFunction());
},
APICallFunction: function () {
  // Call API with the updated value
}
要點(diǎn)二

設(shè)想有一個(gè)需求,需要在在onClick里累加兩次,如下

  onClick = () => {
    this.setState({ index: this.state.index + 1 });
    this.setState({ index: this.state.index + 1 });
  }

在react眼中,這個(gè)方法最終會(huì)變成

Object.assign(
  previousState,
  {index: state.index+ 1},
  {index: state.index+ 1},
  ...
)

由于后面的數(shù)據(jù)會(huì)覆蓋前面的更改,所以最終只加了一次.所以如果是下一個(gè)state依賴前一個(gè)state的話,推薦給setState傳function

onClick = () => {
    this.setState((prevState, props) => {
      return {quantity: prevState.quantity + 1};
    });
    this.setState((prevState, props) => {
      return {quantity: prevState.quantity + 1};
    });
}

以上是使用setState的兩個(gè)注意事項(xiàng),接下來(lái)我們來(lái)看看setState被調(diào)用之后,更新組件的過(guò)程,下面是一個(gè)簡(jiǎn)單的流程圖。

下面來(lái)逐步的解析圖里的流程。

一、setState ReactBaseClassses.js
ReactComponent.prototype.setState = function (partialState, callback) {
  //  將setState事務(wù)放進(jìn)隊(duì)列中
  this.updater.enqueueSetState(this, partialState);
  if (callback) {
    this.updater.enqueueCallback(this, callback, "setState");
  }
};

這里的partialState可以傳object,也可以傳function,它會(huì)產(chǎn)生新的state以一種Object.assgine()的方式跟舊的state進(jìn)行合并。

二、enqueueSetState
  enqueueSetState: function (publicInstance, partialState) {
     // 獲取當(dāng)前組件的instance
    var internalInstance = getInternalInstanceReadyForUpdate(publicInstance, "setState");
     
     // 將要更新的state放入一個(gè)數(shù)組里
     var queue = internalInstance._pendingStateQueue || (internalInstance._pendingStateQueue = []);
    queue.push(partialState);
     
     //  將要更新的component instance也放在一個(gè)隊(duì)列里
    enqueueUpdate(internalInstance);
  }

這段代碼可以得知,enqueueSetState 做了兩件事:
1、將新的state放進(jìn)數(shù)組里
2、用enqueueUpdate來(lái)處理將要更新的實(shí)例對(duì)象

三、enqueueUpdate ReactUpdates.js
function enqueueUpdate(component) {
  // 如果沒(méi)有處于批量創(chuàng)建/更新組件的階段,則處理update state事務(wù)
  if (!batchingStrategy.isBatchingUpdates) {
    batchingStrategy.batchedUpdates(enqueueUpdate, component);
    return;
  }
  // 如果正處于批量創(chuàng)建/更新組件的過(guò)程,將當(dāng)前的組件放在dirtyComponents數(shù)組中
  dirtyComponents.push(component);
}

由這段代碼可以看到,當(dāng)前如果正處于創(chuàng)建/更新組件的過(guò)程,就不會(huì)立刻去更新組件,而是先把當(dāng)前的組件放在dirtyComponent里,所以不是每一次的setState都會(huì)更新組件~。

這段代碼就解釋了我們常常聽(tīng)說(shuō)的:setState是一個(gè)異步的過(guò)程,它會(huì)集齊一批需要更新的組件然后一起更新。

而batchingStrategy 又是個(gè)什么東西呢?

四、batchingStrategy ReactDefaultBatchingStrategy.js
var ReactDefaultBatchingStrategy = {
  // 用于標(biāo)記當(dāng)前是否出于批量更新
  isBatchingUpdates: false,
  // 當(dāng)調(diào)用這個(gè)方法時(shí),正式開(kāi)始批量更新
  batchedUpdates: function (callback, a, b, c, d, e) {
    var alreadyBatchingUpdates = ReactDefaultBatchingStrategy.isBatchingUpdates;

    ReactDefaultBatchingStrategy.isBatchingUpdates = true;

    // 如果當(dāng)前事務(wù)正在更新過(guò)程在中,則調(diào)用callback,既enqueueUpdate
    if (alreadyBatchingUpdates) {
      return callback(a, b, c, d, e);
    } else {
    // 否則執(zhí)行更新事務(wù)
      return transaction.perform(callback, null, a, b, c, d, e);
    }
  }
};

這里注意兩點(diǎn):
1、如果當(dāng)前事務(wù)正在更新過(guò)程中,則使用enqueueUpdate將當(dāng)前組件放在dirtyComponent里。
2、如果當(dāng)前不在更新過(guò)程的話,則執(zhí)行更新事務(wù)。

五、transaction
/**
 * 
 *                       wrappers (injected at creation time)
 *                                      +        +
 *                                      |        |
 *                    +-----------------|--------|--------------+
 *                    |                 v        |              |
 *                    |      +---------------+   |              |
 *                    |   +--|    wrapper1   |---|----+         |
 *                    |   |  +---------------+   v    |         |
 *                    |   |          +-------------+  |         |
 *                    |   |     +----|   wrapper2  |--------+   |
 *                    |   |     |    +-------------+  |     |   |
 *                    |   |     |                     |     |   |
 *                    |   v     v                     v     v   | wrapper
 *                    | +---+ +---+   +---------+   +---+ +---+ | invariants
 * perform(anyMethod) | |   | |   |   |         |   |   | |   | | maintained
 * +----------------->|-|---|-|---|-->|anyMethod|---|---|-|---|-|-------->
 *                    | |   | |   |   |         |   |   | |   | |
 *                    | |   | |   |   |         |   |   | |   | |
 *                    | |   | |   |   |         |   |   | |   | |
 *                    | +---+ +---+   +---------+   +---+ +---+ |
 *                    |  initialize                    close    |
 *                    +-----------------------------------------+
 * 
*/

簡(jiǎn)單說(shuō)明一下transaction對(duì)象,它暴露了一個(gè)perform的方法,用來(lái)執(zhí)行anyMethod,在anyMethod執(zhí)行的前,需要先執(zhí)行所有wrapper的initialize方法,在執(zhí)行完后,要執(zhí)行所有wrapper的close方法,就辣么簡(jiǎn)單。

在ReactDefaultBatchingStrategy.js,tranction 的 wrapper有兩個(gè) 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)
};

var TRANSACTION_WRAPPERS = [FLUSH_BATCHED_UPDATES, RESET_BATCHED_UPDATES];

可以看到,這兩個(gè)wrapper的initialize都沒(méi)有做什么事情,但是在callback執(zhí)行完之后,RESET_BATCHED_UPDATES 的作用是將isBatchingUpdates置為false,
FLUSH_BATCHED_UPDATES 的作用是執(zhí)行flushBatchedUpdates,然后里面會(huì)循環(huán)所有dirtyComponent,調(diào)用updateComponent來(lái)執(zhí)行所有的生命周期方法,componentWillReceiveProps, shouldComponentUpdate, componentWillUpdate, render, componentDidUpdate 最后實(shí)現(xiàn)組件的更新。

以上即為setState的實(shí)現(xiàn)過(guò)程,最后還是用一個(gè)流程圖在做一個(gè)總結(jié)吧~

參考文檔:

https://zhuanlan.zhihu.com/p/...

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

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

相關(guān)文章

  • 揭密“==”隱藏下的類型轉(zhuǎn)換

    摘要:當(dāng)轉(zhuǎn)換后的原始數(shù)據(jù)類型為類型或者類型,則繼續(xù)轉(zhuǎn)換成類型。具體流程圖如下備注的數(shù)據(jù)類型可以分為以下兩種原始數(shù)據(jù)類型才引入的引用類型類型類型轉(zhuǎn)換成類型的規(guī)則類型類型標(biāo)準(zhǔn)的數(shù)字格式如果是標(biāo)準(zhǔn)的數(shù)字格式,轉(zhuǎn)換成類型相比不用多說(shuō),比如下面這幾個(gè)栗子 拋磚引玉 按照正常的邏輯來(lái)說(shuō),我們判斷兩個(gè)值是否相等會(huì)遵循以下規(guī)則:showImg(https://segmentfault.com/img/rem...

    guqiu 評(píng)論0 收藏0
  • 揭密微信跳一跳小游戲那些外掛

    摘要:所以,我們這個(gè)小游戲發(fā)布以后,我們就開(kāi)始花了很多很多時(shí)間來(lái)打擊外掛。二距離判斷像素點(diǎn)判斷該方法采用自目前最火的跳一跳小游戲輔助程序。 作者:Hahn, 騰訊高級(jí)UI工程師商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系騰訊WeTest獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。 原文鏈接:http://wetest.qq.com/lab/view/364.html WeTest 導(dǎo)讀 張小龍:這個(gè)游戲發(fā)布以后,其實(shí)它的效果有點(diǎn)超...

    lyning 評(píng)論0 收藏0
  • setState, forceUpdate, unstable_batchedUpdates看Re

    摘要:是事件回調(diào),有時(shí)機(jī)執(zhí)行邏輯,所以為,,是合并的,結(jié)束之后被重新設(shè)置為。沒(méi)有控制權(quán)的情況有很多回調(diào),網(wǎng)絡(luò)回調(diào)等等。的說(shuō)明從函數(shù)名上理解強(qiáng)制更新。所以可以簡(jiǎn)單的理解為,只不過(guò)這個(gè)是不調(diào)用自己的聲明周期的。 setState同步異步問(wèn)題,React批量更新一直是一個(gè)比較模糊的問(wèn)題,本文希望從框架設(shè)計(jì)的角度說(shuō)明一下這個(gè)問(wèn)題。 React有個(gè)UI = f(data) 公式:UI是由data推導(dǎo)...

    Simon_Zhou 評(píng)論0 收藏0
  • setState promise 化的探討 體會(huì) React 團(tuán)隊(duì)設(shè)計(jì)思想

    摘要:我們來(lái)從設(shè)計(jì)思想上,和官方團(tuán)隊(duì)的回應(yīng)上,了解一下否決理由。此外,還有一個(gè)方法新的接口設(shè)計(jì)支持接收一個(gè)回調(diào)函數(shù),當(dāng)其子組件掛載時(shí),這個(gè)回調(diào)函數(shù)就會(huì)相應(yīng)觸發(fā)。 從 setState 那個(gè)眾所周知的小秘密說(shuō)起... 在 React 組件中,調(diào)用 this.setState() 是最基本的場(chǎng)景。這個(gè)方法描述了 state 的變化、觸發(fā)了組件 re-rendering。但是,也許看似平常的 th...

    caiyongji 評(píng)論0 收藏0
  • setState promise 化的探討 體會(huì) React 團(tuán)隊(duì)設(shè)計(jì)思想

    摘要:我們來(lái)從設(shè)計(jì)思想上,和官方團(tuán)隊(duì)的回應(yīng)上,了解一下否決理由。此外,還有一個(gè)方法新的接口設(shè)計(jì)支持接收一個(gè)回調(diào)函數(shù),當(dāng)其子組件掛載時(shí),這個(gè)回調(diào)函數(shù)就會(huì)相應(yīng)觸發(fā)。 從 setState 那個(gè)眾所周知的小秘密說(shuō)起... 在 React 組件中,調(diào)用 this.setState() 是最基本的場(chǎng)景。這個(gè)方法描述了 state 的變化、觸發(fā)了組件 re-rendering。但是,也許看似平常的 th...

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

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

0條評(píng)論

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