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

資訊專欄INFORMATION COLUMN

談?wù)凴eact中Diff算法的策略及實(shí)現(xiàn)

Scliang / 2581人閱讀

摘要:并且處理特殊屬性,比如事件綁定。之后根據(jù)差異對(duì)象操作元素位置變動(dòng),刪除,添加等。當(dāng)節(jié)點(diǎn)數(shù)過(guò)大或者頁(yè)面更新次數(shù)過(guò)多時(shí),頁(yè)面卡頓的現(xiàn)象會(huì)比較明顯。基于注意使用來(lái)減少組件不必要的更新。

1、什么是Diff算法

傳統(tǒng)Diff:diff算法即差異查找算法;對(duì)于Html DOM結(jié)構(gòu)即為tree的差異查找算法;而對(duì)于計(jì)算兩顆樹(shù)的差異時(shí)間復(fù)雜度為O(n^3),顯然成本太高,React不可能采用這種傳統(tǒng)算法;

React Diff:

之前說(shuō)過(guò),React采用虛擬DOM技術(shù)實(shí)現(xiàn)對(duì)真實(shí)DOM的映射,即React Diff算法的差異查找實(shí)質(zhì)是對(duì)兩個(gè)JavaScript對(duì)象的差異查找;

基于三個(gè)策略:

Web UI 中 DOM 節(jié)點(diǎn)跨層級(jí)的移動(dòng)操作特別少,可以忽略不計(jì)。(tree diff)

擁有相同類的兩個(gè)組件將會(huì)生成相似的樹(shù)形結(jié)構(gòu),擁有不同類的兩個(gè)組件將會(huì)生成不同的樹(shù)形結(jié)(component diff)

對(duì)于同一層級(jí)的一組子節(jié)點(diǎn),它們可以通過(guò)唯一 id 進(jìn)行區(qū)分。(element diff)

2、React Diff算法解讀

首先需要明確,只有在React更新階段才會(huì)有Diff算法的運(yùn)用;

React更新機(jī)制:

React Diff算法優(yōu)化策略圖:

React更新階段會(huì)對(duì)ReactElement類型判斷而進(jìn)行不同的操作;ReactElement類型包含三種即:文本、Dom、組件;

每個(gè)類型的元素更新處理方式:

自定義元素的更新,主要是更新render出的節(jié)點(diǎn),做甩手掌柜交給render出的節(jié)點(diǎn)的對(duì)應(yīng)component去管理更新。

text節(jié)點(diǎn)的更新很簡(jiǎn)單,直接更新文案。

瀏覽器基本元素的更新,分為兩塊:

更新屬性,對(duì)比出前后屬性的不同,局部更新。并且處理特殊屬性,比如事件綁定。

子節(jié)點(diǎn)的更新,子節(jié)點(diǎn)更新主要是找出差異對(duì)象,找差異對(duì)象的時(shí)候也會(huì)使用上面的shouldUpdateReactComponent來(lái)判斷,如果是可以直接更新的就會(huì)遞歸調(diào)用子節(jié)點(diǎn)的更新,這樣也會(huì)遞歸查找差異對(duì)象。不可直接更新的刪除之前的對(duì)象或添加新的對(duì)象。之后根據(jù)差異對(duì)象操作dom元素(位置變動(dòng),刪除,添加等)。

事實(shí)上Diff算法只被調(diào)用于React更新階段的DOM元素更新過(guò)程;為什么這么說(shuō)?

1、 如果為更新文本類型,內(nèi)容不同就直接更新替換,并不會(huì)調(diào)用復(fù)雜的Diff算法:

 ReactDOMTextComponent.prototype.receiveComponent(nextText, transaction) {
    //與之前保存的字符串比較
    if (nextText !== this._currentElement) {
      this._currentElement = nextText;
      var nextStringText = "" + nextText;
      if (nextStringText !== this._stringText) {
        this._stringText = nextStringText;
        var commentNodes = this.getHostNode();
        // 替換文本元素
        DOMChildrenOperations.replaceDelimitedText(
          commentNodes[0],
          commentNodes[1],
          nextStringText
        );
      }
    }
  }

2、對(duì)于自定義組件元素:

class Tab extends Component {
    constructor(props) {
        super(props);
        this.state = {
            index: 1,
        }
    }
    shouldComponentUpdate() {
        ....
    }
    render() {
        return (
            

item1

item1

) } }

需要明確的是,何為組件,可以說(shuō)組件只不過(guò)是一段Html結(jié)構(gòu)的包裝容器,并且具備管理這段Html結(jié)構(gòu)的狀態(tài)等能力;

如上述Tab組件:它的實(shí)質(zhì)內(nèi)容就是render函數(shù)返回的Html結(jié)構(gòu),而我們所說(shuō)的Tab類就是這段Html結(jié)構(gòu)的包裝容器(可以理解為一個(gè)包裝盒子);

在React渲染機(jī)制圖中可以看到,自定義組件的最后結(jié)合React Diff優(yōu)化策略一(不同類的兩個(gè)組件具備不同的結(jié)構(gòu))

3、基本元素:

ReactDOMComponent.prototype.receiveComponent = function(nextElement, transaction, context) {
    var prevElement = this._currentElement;
    this._currentElement = nextElement;
    this.updateComponent(transaction, prevElement, nextElement, context);
}

ReactDOMComponent.prototype.updateComponent = function(transaction, prevElement, nextElement, context) {
    //需要多帶帶的更新屬性
    this._updateDOMProperties(lastProps, nextProps, transaction, isCustomComponentTag);
    //再更新子節(jié)點(diǎn)
    this._updateDOMChildren(
      lastProps,
      nextProps,
      transaction,
      context
    );

    // ......
}

在this._updateDOMChildren方法內(nèi)部才調(diào)用了diff算法。

3、React中Diff算法的實(shí)現(xiàn)
_updateChildren: function(nextNestedChildrenElements, transaction, context) {
    var prevChildren = this._renderedChildren;
    var removedNodes = {};
    var mountImages = [];

    // 獲取新的子元素?cái)?shù)組
    var nextChildren = this._reconcilerUpdateChildren(
      prevChildren,
      nextNestedChildrenElements,
      mountImages,
      removedNodes,
      transaction,
      context
    );

    if (!nextChildren && !prevChildren) {
      return;
    }

    var updates = null;
    var name;
    var nextIndex = 0;
    var lastIndex = 0;
    var nextMountIndex = 0;
    var lastPlacedNode = null;

    for (name in nextChildren) {
      if (!nextChildren.hasOwnProperty(name)) {
        continue;
      }
      var prevChild = prevChildren && prevChildren[name];
      var nextChild = nextChildren[name];
      if (prevChild === nextChild) {
        // 同一個(gè)引用,說(shuō)明是使用的同一個(gè)component,所以我們需要做移動(dòng)的操作
        // 移動(dòng)已有的子節(jié)點(diǎn)
        // NOTICE:這里根據(jù)nextIndex, lastIndex決定是否移動(dòng)
        updates = enqueue(
          updates,
          this.moveChild(prevChild, lastPlacedNode, nextIndex, lastIndex)
        );

        // 更新lastIndex
        lastIndex = Math.max(prevChild._mountIndex, lastIndex);
        // 更新component的.mountIndex屬性
        prevChild._mountIndex = nextIndex;

      } else {
        if (prevChild) {
          // 更新lastIndex
          lastIndex = Math.max(prevChild._mountIndex, lastIndex);
        }

        // 添加新的子節(jié)點(diǎn)在指定的位置上
        updates = enqueue(
          updates,
          this._mountChildAtIndex(
            nextChild,
            mountImages[nextMountIndex],
            lastPlacedNode,
            nextIndex,
            transaction,
            context
          )
        );


        nextMountIndex++;
      }

      // 更新nextIndex
      nextIndex++;
      lastPlacedNode = ReactReconciler.getHostNode(nextChild);
    }

    // 移除掉不存在的舊子節(jié)點(diǎn),和舊子節(jié)點(diǎn)和新子節(jié)點(diǎn)不同的舊子節(jié)點(diǎn)
    for (name in removedNodes) {
      if (removedNodes.hasOwnProperty(name)) {
        updates = enqueue(
          updates,
          this._unmountChild(prevChildren[name], removedNodes[name])
        );
      }
    }
  }
5、基于中Diff的開(kāi)發(fā)建議

基于tree diff:

開(kāi)發(fā)組件時(shí),注意保持DOM結(jié)構(gòu)的穩(wěn)定;即,盡可能少地動(dòng)態(tài)操作DOM結(jié)構(gòu),尤其是移動(dòng)操作。

當(dāng)節(jié)點(diǎn)數(shù)過(guò)大或者頁(yè)面更新次數(shù)過(guò)多時(shí),頁(yè)面卡頓的現(xiàn)象會(huì)比較明顯。

這時(shí)可以通過(guò) CSS 隱藏或顯示節(jié)點(diǎn),而不是真的移除或添加 DOM 節(jié)點(diǎn)。

基于component diff

注意使用 shouldComponentUpdate() 來(lái)減少組件不必要的更新。

對(duì)于類似的結(jié)構(gòu)應(yīng)該盡量封裝成組件,既減少代碼量,又能減少component diff的性能消耗。

基于element diff

對(duì)于列表結(jié)構(gòu),盡量減少類似將最后一個(gè)節(jié)點(diǎn)移動(dòng)到列表首部的操作,當(dāng)節(jié)點(diǎn)數(shù)量過(guò)大或更新操作過(guò)于頻繁時(shí),在一定程度上會(huì)影響 React 的渲染性能。

接下來(lái)手動(dòng)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的Diff算法即將更新,敬請(qǐng)期待~~~

“積跬步、行千里”—— 持續(xù)更新中~,喜歡留下個(gè)贊哦!

往期經(jīng)典好文:

團(tuán)隊(duì)合作必備的Git操作

談?wù)凧s前端規(guī)范化

從React渲染流程分析Diff算法

相關(guān)專欄推薦:

React學(xué)習(xí)之路

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

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

相關(guān)文章

  • 談?wù)?/em>ReactDiff算法策略實(shí)現(xiàn)

    摘要:并且處理特殊屬性,比如事件綁定。之后根據(jù)差異對(duì)象操作元素位置變動(dòng),刪除,添加等。當(dāng)節(jié)點(diǎn)數(shù)過(guò)大或者頁(yè)面更新次數(shù)過(guò)多時(shí),頁(yè)面卡頓的現(xiàn)象會(huì)比較明顯?;谧⒁馐褂脕?lái)減少組件不必要的更新。 1、什么是Diff算法 傳統(tǒng)Diff:diff算法即差異查找算法;對(duì)于Html DOM結(jié)構(gòu)即為tree的差異查找算法;而對(duì)于計(jì)算兩顆樹(shù)的差異時(shí)間復(fù)雜度為O(n^3),顯然成本太高,React不可能采用這種...

    HmyBmny 評(píng)論0 收藏0
  • react diff算法

    摘要:算法的本質(zhì)是對(duì)傳統(tǒng)遍歷算法的優(yōu)化策略用三大策略將復(fù)雜度轉(zhuǎn)化為復(fù)雜度策略一中節(jié)點(diǎn)跨層級(jí)的移動(dòng)操作特別少,可以忽略不計(jì)。當(dāng)節(jié)點(diǎn)處于同一層級(jí)時(shí),提供三種節(jié)點(diǎn)操作刪除插入移動(dòng)。在舊的節(jié)點(diǎn)中的,它的,不滿足的條件,因此不做移動(dòng)操作。 一、react diff算法 diff算法的作用 計(jì)算出Virtual DOM中真正變化的部分,并只針對(duì)該部分進(jìn)行原生DOM操作,而非重新渲染整個(gè)頁(yè)面。 傳統(tǒng)di...

    imccl 評(píng)論0 收藏0
  • react基本原理性能優(yōu)化

    摘要:對(duì)同一層級(jí)的子節(jié)點(diǎn)進(jìn)行處理時(shí),會(huì)根據(jù)進(jìn)行簡(jiǎn)要的復(fù)用。二性能優(yōu)化方案由于中性能主要耗費(fèi)在于階段的算法,因此性能優(yōu)化也主要針對(duì)算法。此時(shí)最常用的優(yōu)化方案即為方法?;蛘咧苯邮褂?,原理一致。 一、從React原理談起 react是什么? showImg(https://segmentfault.com/img/bVbcYvf?w=1140&h=384); react是用于構(gòu)建用戶界面的JS框架...

    VincentFF 評(píng)論0 收藏0
  • react基本原理性能優(yōu)化

    摘要:對(duì)同一層級(jí)的子節(jié)點(diǎn)進(jìn)行處理時(shí),會(huì)根據(jù)進(jìn)行簡(jiǎn)要的復(fù)用。或者直接使用,原理一致。 一、從React原理談起 react是什么? showImg(https://segmentfault.com/img/bVbcYvf?w=1140&h=384); react是用于構(gòu)建用戶界面的JS框架。因此react只負(fù)責(zé)解決view層的渲染。 react做了什么? Virtual Dom模型 生命周期...

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

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

0條評(píng)論

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