国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

setState異步、同步與進(jìn)階

widuu / 1026人閱讀

摘要:根本原因在于,并不是真正意義上的異步操作,它只是模擬了異步的行為。而合成事件和生命周期函數(shù)中,是受控制的,其會(huì)將設(shè)置為,從而走的是類似異步的那一套??偨Y(jié)此處總結(jié)是直接引用了只在合成事件和鉤子函數(shù)中是異步的,在原生事件和中都是同步的。

如何使用setState

在 React 日常的使用中,一個(gè)很重要的點(diǎn)就是,不要直接去修改 state。例如:this.state.count = 1是無(wú)法觸發(fā) React 去更新視圖的。因?yàn)镽eact的機(jī)制規(guī)定,一個(gè)state的更新,首先需要調(diào)用 setState 方法。

this.setState({
    count: 1
})

這樣便能觸發(fā)重新渲染。稍有經(jīng)驗(yàn)的開發(fā)者會(huì)知道,setState 方法其實(shí)是 “異步” 的。即立馬執(zhí)行之后,是無(wú)法直接獲取到最新的 state 的,需要經(jīng)過 React 對(duì) state 的所有改變進(jìn)行合并處理之后,才會(huì)去計(jì)算新的虛擬dom,再根據(jù)最新的虛擬dom去重新渲染真實(shí)dom。

class App extends Component {
    state = {
        count: 0
    }

    componentDidMount(){
        this.setState({count: this.state.count + 1})
        console.log(this.state.count) // 0
    }

    render(){
        ...
    }
}

demo請(qǐng)點(diǎn)擊

那怎么才能獲取到修改后的state呢?React為我們提供了一個(gè)回調(diào)去實(shí)現(xiàn)。

...
this.setState({count: this.state.count + 1}, ()=>{
    console.log(this.state.count) // 1
})
...

回調(diào)里的 state 便是最新的了,原因是該回調(diào)的執(zhí)行時(shí)機(jī)在于state合并處理之后。如果我們這樣去做:

...
    this.setState({count: this.state.count + 1})
    this.setState({count: this.state.count + 1})
...

實(shí)際最終的 count 會(huì)等于 1,原因是執(zhí)行時(shí)得到的 this.state.count = 0。那怎么實(shí)現(xiàn)結(jié)果為 2 呢?

...
this.setState(prevState => {count: prevState.count + 1});
this.setState(prevState => {count: prevState.count + 1});
...

setState()實(shí)際上可以接受一個(gè)函數(shù)作為參數(shù),函數(shù)的首個(gè)參數(shù)就是上一次的state。

以上介紹了setState的三種使用方式,下面我們來(lái)看看它們的執(zhí)行時(shí)機(jī)是怎樣的:

...
    this.setState({ count: this.state.count + 1 });
    console.log("console: " + this.state.count); // 0
    this.setState({ count: this.state.count + 1 }, () => {
      console.log("console from callback: " + this.state.count); // 2
    });
    this.setState(prevState => {
      console.log("console from func: " + prevState.count); // 1
      return {
        count: prevState.count + 1
      };
    }, ()=>{
      console.log("last console: "+ this.state.count)
    });
...

執(zhí)行結(jié)果:

console: 0 
console from func: 1 
console from callback: 2
last console: 2 

React 其實(shí)會(huì)維護(hù)著一個(gè) state 的更新隊(duì)列,每次調(diào)用 setState 都會(huì)先把當(dāng)前修改的 state 推進(jìn)這個(gè)隊(duì)列,在最后,React 會(huì)對(duì)這個(gè)隊(duì)列進(jìn)行合并處理,然后去執(zhí)行回調(diào)。根據(jù)最終的合并結(jié)果再去走下面的流程(更新虛擬dom,觸發(fā)渲染)。

setState為什么要設(shè)計(jì)成異步的

因?yàn)?b>setState()之后無(wú)法立馬獲取最新的 state,給人的感覺便是異步去設(shè)置狀態(tài)。也確實(shí)是有異步的感覺(實(shí) 際原理后面講訴)。那么為什么 React 要把狀態(tài)的更新設(shè)計(jì)成這種方式呢?直接 this.state.count = 1 不好嗎?

有興趣的可以點(diǎn)擊看看:https://github.com/facebook/react/issues/11527#issuecomment-360199710

這邊簡(jiǎn)單總結(jié)下:

保證內(nèi)部的一致性:即使state是同步更新,props也不是。(你只有在父組件重新渲染時(shí)才能知道props

state的更新延緩到最后批量合并再去渲染對(duì)于應(yīng)用的性能優(yōu)化是有極大好處的,如果每次的狀態(tài)改變都去重新渲染真實(shí)dom,那么它將帶來(lái)巨大的性能消耗。

setState真的是異步嗎

我們先來(lái)看一段代碼,執(zhí)行前建議大家先預(yù)估下結(jié)果:

demo請(qǐng)點(diǎn)擊

class App extends Component {
  state = {
    count: 0
  };

  componentDidMount() {
    // 生命周期中調(diào)用
    this.setState({ count: this.state.count + 1 });
    console.log("lifecycle: " + this.state.count);
    setTimeout(() => {
      // setTimeout中調(diào)用
      this.setState({ count: this.state.count + 1 });
      console.log("setTimeout: " + this.state.count);
    }, 0);
    document.getElementById("div2").addEventListener("click", this.increment2);
  }

  increment = () => {
    // 合成事件中調(diào)用
    this.setState({ count: this.state.count + 1 });
    console.log("react event: " + this.state.count);
  };

  increment2 = () => {
    // 原生事件中調(diào)用
    this.setState({ count: this.state.count + 1 });
    console.log("dom event: " + this.state.count);
  };

  render() {
    return (
      

couont: {this.state.count}

click me and count+1
click me and count+1
); } }

探討前,我們先簡(jiǎn)單了解下react的事件機(jī)制:react為了解決跨平臺(tái),兼容性問題,自己封裝了一套事件機(jī)制,代理了原生的事件,像在jsx中常見的onClick、onChange這些都是合成事件。

那么以上4種方式調(diào)用setState(),后面緊接著去取最新的state,按之前講的異步原理,應(yīng)該是取不到的。然而,setTimeout中調(diào)用以及原生事件中調(diào)用的話,是可以立馬獲取到最新的state的。根本原因在于,setState并不是真正意義上的異步操作,它只是模擬了異步的行為。React中會(huì)去維護(hù)一個(gè)標(biāo)識(shí)(isBatchingUpdates),判斷是直接更新還是先暫存state進(jìn)隊(duì)列。setTimeout以及原生事件都會(huì)直接去更新state,因此可以立即得到最新state。而合成事件和React生命周期函數(shù)中,是受React控制的,其會(huì)將isBatchingUpdates設(shè)置為 true,從而走的是類似異步的那一套。

總結(jié)

此處總結(jié)是直接引用了:https://juejin.im/post/5b45c57c51882519790c7441#heading-7

setState 只在合成事件和鉤子函數(shù)中是“異步”的,在原生事件和 setTimeout 中都是同步的。

setState的“異步”并不是說(shuō)內(nèi)部由異步代碼實(shí)現(xiàn),其實(shí)本身執(zhí)行的過程和代碼都是同步的,只是合成事件和鉤子函數(shù)的調(diào)用順序在更新之前,導(dǎo)致在合成事件和鉤子函數(shù)中沒法立馬拿到更新后的值,形式了所謂的“異步”,當(dāng)然可以通過第二個(gè)參數(shù) setState(partialState, callback) 中的callback拿到更新后的結(jié)果。

setState 的批量更新優(yōu)化也是建立在“異步”(合成事件、鉤子函數(shù))之上的,在原生事件和setTimeout 中不會(huì)批量更新,在“異步”中如果對(duì)同一個(gè)值進(jìn)行多次 setStatesetState 的批量更新策略會(huì)對(duì)其進(jìn)行覆蓋,取最后一次的執(zhí)行,如果是同時(shí) setState 多個(gè)不同的值,在更新時(shí)會(huì)對(duì)其進(jìn)行合并批量更新。

參考:

你真的理解setState嗎?

淺出深入setState(上)

淺出深入setState(下)

坦白說(shuō),自己的水平還是挺有限的,還需要努力努力再努力。只有懂了很多,才能寫出有意義的東西吧?,F(xiàn)在寫的,大多都是根據(jù)別人的文章,自己理解了之后,換成自己的語(yǔ)言再表達(dá)一遍而已。。

慢慢來(lái),總有一天可以突破這個(gè)界限的,真正寫出屬于自己的東西。

另外,真心感謝這些文章的作者給予的幫助。

關(guān)于我

微信號(hào):rcgrcg,歡迎交友~

為了生計(jì),我也接外包項(xiàng)目的哦~

網(wǎng)站搭建(PC、H5、前后端全包,我們有團(tuán)隊(duì)的哦),APP開發(fā)(安卓和IOS),都是有成功案例的哦。

有興趣的請(qǐng)聯(lián)系我!!服務(wù)包您滿意的那種!!

Good luck!
2018-11-18 廈門

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/108682.html

相關(guān)文章

  • 【React進(jìn)階系列】 setState機(jī)制

    摘要:的批量更新優(yōu)化也是建立在異步合成事件鉤子函數(shù)之上的,在原生事件和中不會(huì)批量更新,在異步中如果對(duì)同一個(gè)值進(jìn)行多次,的批量更新策略會(huì)對(duì)其進(jìn)行覆蓋,取最后一次的執(zhí)行,如果是同時(shí)多個(gè)不同的值,在更新時(shí)會(huì)對(duì)其進(jìn)行合并批量更新。 api解析: setState(updater, [callback]) updater: 更新數(shù)據(jù) FUNCTION/OBJECT callback: 更新成功后的回...

    Yuqi 評(píng)論0 收藏0
  • React 深入系列4:組件的生命周期

    摘要:因?yàn)槭巧钊胂盗形恼?,本文不?huì)仔細(xì)介紹每個(gè)生命周期方法的使用,而是會(huì)重點(diǎn)講解在使用組件生命周期時(shí),經(jīng)常遇到的疑問和錯(cuò)誤使用方式。父組件發(fā)生更新導(dǎo)致的組件更新,生命周期方法的調(diào)用情況同上所述。 文:徐超,《React進(jìn)階之路》作者授權(quán)發(fā)布,轉(zhuǎn)載請(qǐng)注明作者及出處 React 深入系列4:組件的生命周期 React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深...

    warnerwu 評(píng)論0 收藏0
  • React 深入系列4:組件的生命周期

    摘要:因?yàn)槭巧钊胂盗形恼?,本文不?huì)仔細(xì)介紹每個(gè)生命周期方法的使用,而是會(huì)重點(diǎn)講解在使用組件生命周期時(shí),經(jīng)常遇到的疑問和錯(cuò)誤使用方式。父組件發(fā)生更新導(dǎo)致的組件更新,生命周期方法的調(diào)用情況同上所述。 React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深對(duì)React的理解,以及在項(xiàng)目中更加靈活地使用React。 組件是構(gòu)建React應(yīng)用的基本單位,組件需要具備數(shù)據(jù)...

    alexnevsky 評(píng)論0 收藏0
  • React 生命周期

    摘要:同步渲染的痛點(diǎn)當(dāng)應(yīng)用的組件樹特別龐大時(shí),由于是單線程的,重新渲染一旦開始,中間不會(huì)停,如果這時(shí)候用戶去操作,比如輸入,點(diǎn)擊按鈕,此時(shí)頁(yè)面是沒有響應(yīng)的。 React生命周期 基礎(chǔ)生命周期鉤子 constructor 如果你不初始化狀態(tài),也不綁定方法,那么你就不需要為React組件實(shí)現(xiàn)構(gòu)造函數(shù)。在這里初始化狀態(tài)可以直接對(duì)this.state賦值,在這里使用props時(shí),應(yīng)當(dāng)通過this.p...

    Dean 評(píng)論0 收藏0
  • 關(guān)于React中的setState

    摘要:而在第二個(gè)參數(shù)中我們輸出了改變后的即第五行輸出,表明我們的更改生效了。而在的回調(diào)內(nèi),我們還調(diào)用了一個(gè)定義于內(nèi)的事件函數(shù),但是該事件函數(shù)內(nèi)的也是同步的形式。 在react中,setState是用以改變class組件狀態(tài)的函數(shù),它有兩種用法:一 傳入一個(gè)updater函數(shù),該函數(shù)有兩個(gè)參數(shù),一個(gè)是當(dāng)前的state,還有一個(gè)是當(dāng)前的props。該函數(shù)的返回值需要是一個(gè)更改的state值的對(duì)象...

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

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

0條評(píng)論

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