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

資訊專欄INFORMATION COLUMN

從setState, forceUpdate, unstable_batchedUpdates看Re

Simon_Zhou / 1190人閱讀

摘要:是事件回調,有時機執行邏輯,所以為,,是合并的,結束之后被重新設置為。沒有控制權的情況有很多回調,網絡回調等等。的說明從函數名上理解強制更新。所以可以簡單的理解為,只不過這個是不調用自己的聲明周期的。

setState同步異步問題,React批量更新一直是一個比較模糊的問題,本文希望從框架設計的角度說明一下這個問題。

React有個UI = f(data) 公式:UI是由data推導出來的,所以在寫應用的時候,我們只需要關心數據的改變,只需data ---> data", 那么UI ---> UI",在這個過程中,我們其實并不關心UI是怎么變化到UI‘的(即DOM的變化),這部分工作是React替我們處理了。

那么React是如何知道當數據變化的時候,需要修改哪些DOM的呢?最簡單暴力的是,每次都重新構建整個DOM樹。實際上,React使用的是一種叫virtual-dom的技術:用JS對象來表示DOM結構,通過比較前后JS對象的差異,來獲得DOM樹的增量修改。virtual-dom通過暴力的js計算,大大減少了DOM操作,讓UI = f(data)這種模型性能不是那么的慢,當然你用原生JS/jquery直接操作DOM永遠是最快的。

setState 批量更新

除了virtual-dom的優化,減少數據更新的頻率是另外一種手段,也就是React的批量更新。 比如:

g() {
   this.setState({
        age: 18
    })
    this.setState({
        color: "black‘
    })
}

f() {
    this.setState({
        name: "yank"
    })
    this.g()
}

會被React合成為一次setState調用

f() {
    this.setState({
        name: "yank",
        age: 18, 
        color: "black"
    })
}

我們通過偽碼大概看一下setState是如何合并的。

setState實現

setState(newState) {
    if (this.canMerge) {
        this.updateQueue.push(newState)
        return 
    }
    
    // 下面是真正的更新: dom-diff, lifeCycle...
    ...
}

然后f方法調用

g() {
   this.setState({
        age: 18
    })
    this.setState({
        color: "black‘
    })
}

f() {
    this.canMerge = true
    
    this.setState({
        name: "yank"
    })
    this.g()
    
    this.canMerge = false
    // 通過this.updateQueue合并出finalState
    const finalState = ...  
    // 此時canMerge 已經為false 故而走入時機更新邏輯
    this.setState(finaleState) 
}

可以看出 setState首先會判斷是否可以合并,如果可以合并,就直接返回了。

不過有同學會問:在使用React的時候,我并沒有設置this.canMerge呀?我們的確沒有,是React隱式的幫我們設置了!事件處理函數,聲明周期,這些函數的執行是發生在React內部的,React對它們有完全的控制權。

class A extends React.Component {
    componentDidMount() {
        console.log("...")
    }

    render() {
        return (
{ console.log("hi") }}>
} }

在執行componentDidMount前后,React會執行canMerge邏輯,事件處理函數也是一樣,React委托代理了所有的事件,在執行你的處理函數函數之前,會執行React邏輯,這樣React也是有時機執行canMerge邏輯的。

批量更新是極好滴!我們當然希望任何setState都可以被批量,關鍵點在于React是否有時機執行canMerge邏輯,也就是React對目標函數有沒有控制權。如果沒有控制權,一旦setState提前返回了,就再也沒有機會應用這次更新了。

class A extends React.Component {
    handleClick = () => {
        this.setState({x: 1})
        this.setState({x: 2})
        this.setState({x: 3})
        
        setTimeout(() => {
            this.setState({x: 4})
            this.setState({x: 5})
            this.setState({x: 6})
        }, 0)
    }    
    
    render() {
        return (
} }

handleClick 是事件回調,React有時機執行canMerge邏輯,所以x為1,2,3是合并的,handleClick結束之后canMerge被重新設置為false。注意這里有一個setTimeout(fn, 0)。 這個fn會在handleClick之后調用,而React對setTimeout并沒有控制權,React無法在setTimeout前后執行canMerge邏輯,所以x為4,5,6是無法合并的,所以fn這里會存在3次dom-diff。React沒有控制權的情況有很多: Promise.then(fn), fetch回調,xhr網絡回調等等。

unstable_batchedUpdates 手動合并

那x為4,5,6有辦法合并嗎?是可以的,需要用unstable_batchedUpdates這個API,如下:

class A extends React.Component {
    handleClick = () => {
        this.setState({x: 1})
        this.setState({x: 2})
        this.setState({x: 3})
        
        setTimeout(() => {
            ReactDOM.unstable_batchedUpdates(() => {
                this.setState({x: 4})
                this.setState({x: 5})
                this.setState({x: 6})
            })
        }, 0)
    }    
    
    render() {
        return (
} }

這個API,不用解釋太多,我們看一下它的偽碼就很清楚了

function unstable_batchedUpdates(fn) {
    this.canMerge = true
    
    fn()
    
    this.canMerge = false
    const finalState = ...  //通過this.updateQueue合并出finalState
    this.setState(finaleState)
}

so, unstable_batchedUpdates 里面的setState也是會合并的。

forceUpdate的說明

forceUpdate從函數名上理解:“強制更新”。 既然是“強制更新”有兩個問題容易引起誤解:

forceUpdate 是同步的嗎?“強制”會保證調用然后直接dom-diff嗎?

“強制”更新整個組件樹嗎?包括自己,子孫后代組件嗎?

這兩個問題官方文檔都沒有明確說明。

class A extends React.Component{
    
    handleClick = () => {
        this.forceUpdate()
        this.forceUpdate()
        this.forceUpdate()
        this.forceUpdate()
    }
    
    shouldComponentUpdate() {
        return false
    }
    
    render() {
        return (
            
// 一個組件
) } }

對于第一個問題:forceUpdate在批量與否的表現上,和setState是一樣的。在React有控制權的函數里,是批量的。

對于第二個問題:forceUpdate只會強制本身組件的更新,即不調用“shouldComponentUpdate”直接更新,對于子孫后代組件還是要調用自己的“shouldComponentUpdate”來決定的。

所以forceUpdate 可以簡單的理解為 this.setState({}),只不過這個setState 是不調用自己的“shouldComponentUpdate”聲明周期的。

Fiber 的想象

顯示的讓開發者調用unstable_batchedUpdates是不優雅的,開發者不應該被框架的實現細節影響。但是正如前文所說,React沒有控制權的函數,unstable_batchedUpdates好像是不可避免的。 不過 React16.xfiber架構,可能有所改變。我們看下fiber下的更新

setState(newState){
    this.updateQueue.push(newState)
    requestIdleCallback(performWork)
}

requestIdleCallback 會在瀏覽器空閑時期調用函數,是一個低優先級的函數。

現在我們再考慮一下:

handleClick = () => {
        this.setState({x: 1})
        this.setState({x: 2})
        this.setState({x: 3})
        
        setTimeout(() => {
            this.setState({x: 4})
            this.setState({x: 5})
            this.setState({x: 6})
        }, 0)
    }    

當x為1,2,3,4,5,6時 都會進入更新隊列,而當瀏覽器空閑的時候requestIdleCallback會負責來執行統一的更新。

由于fiber的調度比較復雜,這里只是簡單的說明,具體能不能合并,跟優先級還有其他都有關系。不過fiber的架構的確可以更加優雅的實現批量更新,而且不需要開發者顯示的調用unstable_batchedUpdates

廣告時間

最后,廣告一下我們開源的RN轉小程序引擎alita,alita區別于現有的社區編譯時方案,采用的是運行時處理JSX的方式,詳見這篇文章。

所以alita內置了一個mini-react,這個mini-react同樣提供了合成setState/forceUpdate更新的功能,并對外提供了unstable_batchedUpdates接口。如果你讀react源碼無從下手,可以看一下alita minil-react的實現,這是一個適配小程序的react實現, 且小,代碼在https://github.com/areslabs/alita/tree/master/packages/wx-react。

alita地址:https://github.com/areslabs/alita。 歡迎star & pr & issue

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/105505.html

相關文章

  • 精讀《react-easy-state 源碼》

    摘要:會自動觸發函數內回調函數的執行。因此利用并將依賴置為使代碼在所有渲染周期內,只在初始化執行一次。同時代碼里還對等公共方法進行了包裝,讓這些回調函數中自帶效果。前端精讀幫你篩選靠譜的內容。 1. 引言 react-easy-state 是個比較有趣的庫,利用 Proxy 創建了一個非常易用的全局數據流管理方式。 import React from react; import { stor...

    curlyCheng 評論0 收藏0
  • 關于React中的setState

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

    qieangel2013 評論0 收藏0
  • React Redux: 文檔源碼 - Components篇

    摘要:的作用在文檔中是這么說的給下級組件中的提供可用的的對象。這個文件里的主要是被方法引入,并傳給的,算是一個默認的。表示當前的名稱。這個值表示在里面的值。便于控制,同時某些不需要渲染的,也不會造成渲染。 注:這篇文章只是講解React Redux這一層,并不包含Redux部分。Redux有計劃去學習,等以后學習了Redux源碼以后再做分析注:代碼基于現在(2016.12.29)React ...

    alphahans 評論0 收藏0
  • react: 組件初識 && 生命周期 && 相關說明

    react組件 參考:https://facebook.github.io/re... react的組件是其核心思想部分,react允許將整個ui設計分割稱為獨立的、可復用的隔離模塊,react的組件是一個抽象的類,直接使用reacy.component是沒有很大意義的,所以一般使用的方法就是定義一個 class 來繼承這個component,并且需要實現方法 render();就像下面一樣: ...

    jokester 評論0 收藏0
  • react:組件初識 && 生命周期 && tips

    react組件 參考:https://facebook.github.io/re... react的組件是其核心思想部分,react允許將整個ui設計分割稱為獨立的、可復用的隔離模塊,react的組件是一個抽象的類,直接使用reacy.component是沒有很大意義的,所以一般使用的方法就是定義一個 class 來繼承這個component,并且需要實現方法 render();就像下面一樣: ...

    miqt 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<