国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

React源碼解析18(10)------ 實(shí)現(xiàn)多節(jié)點(diǎn)的Diff算法

這篇具有很好參考價(jià)值的文章主要介紹了React源碼解析18(10)------ 實(shí)現(xiàn)多節(jié)點(diǎn)的Diff算法。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

摘要

在上一篇中,實(shí)現(xiàn)了多節(jié)點(diǎn)的渲染。但是之前寫得diff算法,只能適用于單節(jié)點(diǎn)的情況,例如這種情況:

<div>
	<p>
 		<span></span>
	</p>
</div>

如果對(duì)于多節(jié)點(diǎn)的情況:

<ul>
	<li></li>
	<li></li>
	<li></li>
</ul>

之前實(shí)現(xiàn)的diff算法就不會(huì)有效果了,所以在這一篇中,我們主要實(shí)現(xiàn)針對(duì)于多節(jié)點(diǎn)的diff算法。

實(shí)現(xiàn)之前,我們先將index.js修改一下:

function App() {
  const [num, setNum] = useState(100)
  const click1 = () => {
    console.log(num);
    setNum(num + 1)
  }
  return num % 2 > 0 ? jsx("ul", {
    onClick: click1,
    key: 'ul',
    children: [jsx("li", {
      children: "1",
      key: "1"
    }), jsx("li", {
      children: "2",
      key: "2"
    }), jsx("li", {
      children: "3",
      key: "3"
    })]
  }): jsx("ul", {
    onClick: click1,
    key: 'ul',
    children: [jsx("li", {
      children: "2",
      key: "2"
    }), jsx("li", {
      children: "1",
      key: "1"
    }), jsx("li", {
      children: "3",
      key: "3"
    })]
  });
}

ReactDOM.createRoot(root).render(<App />)

1.修改beginWork流程

在reconcileChildren方法里面,我們判斷了如果element為數(shù)組的情況,就是多節(jié)點(diǎn)。所以我們需要在這里進(jìn)行diff算法的處理。

function reconcileChildren(parent,element) {
  //其他代碼。。。。
  }else if(Array.isArray(element) && element.length > 0) {
    const newChild = diffReconcileManyChildren(parent, element);
    if(newChild) {
      return newChild
    }
  //其他代碼。。。。

所以我們的diff算法那主要是在diffReconcileManyChildren方法里面實(shí)現(xiàn)。

對(duì)于多節(jié)點(diǎn)的Diff,我們需要進(jìn)行以下步驟。

  1. 創(chuàng)建變量lastIndex,用來(lái)標(biāo)記索引
  2. 將舊的filberNode列表,轉(zhuǎn)換為map結(jié)構(gòu),key為filberNode的key,value為filberNode
  3. 遍歷新的element數(shù)組。
  4. 如果element.key可以在map中找到,lastIndex記錄為找到的filberNode的index
  5. 如果找不到,創(chuàng)建新的FilberNode
  6. 繼續(xù)遍歷,如果又在map中找到filberNode,比較fiberNode的index和lastIndex.
  7. 如果index < lastIndex,給filberNode打上移動(dòng)的標(biāo)志

基于上面的步驟,實(shí)現(xiàn)diffReconcileManyChildren方法

function diffReconcileManyChildren(filberNode, element) {
  let firstChild = filberNode.child;
  if(!firstChild) {
    return;
  }
  const head = {
    sibling: null
  };
  const oldChildren = []
  while(firstChild) {
    oldChildren.push(firstChild);
    firstChild = firstChild.sibling;
  }
  const oldMap = new Map();
  oldChildren.forEach((item,index) => {
    item.index = index
    if(item.key) {
      oldMap.set(item.key, item)
    }else{
      oldMap.set(index, item)
    }
  })
  let lastIndex = 0;
  let empty = head
  for(let i=0; i<element.length; i++) {
    if(!element[i].key){
      continue;
    }
    const useFilber = oldMap.get(element[i].key);
    useFilber.sibling = null;
    if(useFilber) {
      if(useFilber.index < lastIndex) {
        useFilber.flags = 'insert'
      }
      useFilber.memoizedProps = element[i]
      lastIndex = useFilber.index;
      empty.sibling = useFilber;
      empty = empty.sibling;
      oldMap.delete(element[i].key)
    }else{
      const filberNode = new FilberNode(HostComponent, element[i].props, element[i].key) 
      filberNode.type = element[i].type
      empty.sibling = filberNode;
      empty = empty.sibling;
    }

  }
  return head.sibling;
}

經(jīng)過(guò)上面的處理,beginWork流程結(jié)束,可復(fù)用的filberNode就不會(huì)重復(fù)創(chuàng)建。

2.修改completeWork流程

在beginWork中,可復(fù)用的節(jié)點(diǎn)已經(jīng)被打上了insert的標(biāo)志,所以在updateCompleteHsotComponent中,我們要判斷是不是insert的標(biāo)志,如果是,就不能無(wú)腦創(chuàng)建,而是通過(guò)移動(dòng)DOM的位置來(lái)復(fù)用DOM。

同時(shí),也要對(duì)同級(jí)的sibling進(jìn)行遞歸處理。

function updateCompleteHostComponent(filberNode) {
  //其他代碼。。。。
  if(element.key === filberNode.key && element.type === filberNode.type) {
    addPropsToDOM(filberNode.stateNode, filberNode.pendingProps);
    if(filberNode.flags === 'insert') {
      const parent = filberNode.return;
      parent.stateNode.insertBefore(filberNode.stateNode, filberNode.sibling?.stateNode)
    }
  //其他代碼
  if(filberNode.sibling) {
    completeWork(filberNode.sibling)
  }
}

在對(duì)HostText的處理中,也要考慮,當(dāng)前的操作是更新還是替換。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-661960.html

function completeHostText(filberNode) {
  //其他代碼。。。。。
  if(parent && parent.stateNode && parent.tag === HostComponent) {
    if(!parent.stateNode) {
      parent.stateNode.appendChild(element);
    }else{
      parent.stateNode.replaceChildren(element);
    }
  }
  //其他代碼。。。。
}

到了這里,關(guān)于React源碼解析18(10)------ 實(shí)現(xiàn)多節(jié)點(diǎn)的Diff算法的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • React源碼解析18(11)------ 實(shí)現(xiàn)多次setState的批處理

    在React中,如果涉及到了多次setState,組件render幾次。setState是同步的還是異步的。這是一個(gè)很常見(jiàn)的面試題。 而本篇文章,就是主要實(shí)現(xiàn)React中,對(duì)于這部分的性能優(yōu)化,我們稱之為批處理。例如當(dāng)我有下面的JSX。 對(duì)于當(dāng)前的點(diǎn)擊事件來(lái)說(shuō),只有最后的setNum(num + 3)是有效的。

    2024年02月11日
    瀏覽(40)
  • vue和react的diff算法源碼

    Vue.js 的 Diff 算法主要基于 Snabbdom,以下是 Vue.js 中虛擬 DOM Diff 算法的簡(jiǎn)化版?zhèn)未a,以便說(shuō)明其基本思想: 這里主要關(guān)注 patchVnode 函數(shù),它是 Diff 算法的核心。Vue.js 的 Diff 算法采用了一種雙端比較的策略,具體步驟如下: 1.同層級(jí)比較: 首先比較新舊節(jié)點(diǎn)的同層級(jí),通過(guò)

    2024年03月15日
    瀏覽(24)
  • React源碼解析18(5)------ 實(shí)現(xiàn)函數(shù)組件【修改beginWork和completeWork】

    React源碼解析18(5)------ 實(shí)現(xiàn)函數(shù)組件【修改beginWork和completeWork】

    經(jīng)過(guò)之前的幾篇文章,我們實(shí)現(xiàn)了基本的jsx,在頁(yè)面渲染的過(guò)程。但是如果是通過(guò)函數(shù)組件寫出來(lái)的組件,還是不能渲染到頁(yè)面上的。 所以這一篇,主要是對(duì)之前寫得方法進(jìn)行修改,從而能夠顯示函數(shù)組件,所以現(xiàn)在我們?cè)趇ndex.js文件中,修改一下jsx的寫法。修改成函數(shù)組件

    2024年02月13日
    瀏覽(20)
  • React源碼解析18(1)------ React.createElement 和 jsx

    React源碼解析18(1)------ React.createElement 和 jsx

    我們知道在React17版本之前,我們?cè)陧?xiàng)目中是一定需要引入react的。 import React from “react” 即便我們有時(shí)候沒(méi)有使用到React,也需要引入。原因是什么呢? 在React項(xiàng)目中,如果我們使用了模板語(yǔ)法JSX,我們知道它要先經(jīng)過(guò)babel的轉(zhuǎn)譯。那babel會(huì)將JSX轉(zhuǎn)換成什么樣子的格式呢? 可

    2024年02月13日
    瀏覽(21)
  • React源碼解析18(2)------ FilberNode,F(xiàn)ilberRootNode結(jié)構(gòu)關(guān)系

    React源碼解析18(2)------ FilberNode,F(xiàn)ilberRootNode結(jié)構(gòu)關(guān)系

    在上一篇,我們實(shí)現(xiàn)了通過(guò)JSX轉(zhuǎn)換為ReactElement的方法,也看到了轉(zhuǎn)換后React元素的結(jié)構(gòu)。但是這個(gè)React元素,并不能很清楚的表達(dá)組件之間的關(guān)系,以及屬性的處理。 所以在React內(nèi)部,會(huì)將所有的React元素轉(zhuǎn)換為Filber樹(shù)。而這一章節(jié),主要就是簡(jiǎn)單描述一下FilberNode的結(jié)構(gòu)。 首

    2024年02月13日
    瀏覽(20)
  • React源碼解析18(4)------ completeWork的工作流程【mount】

    React源碼解析18(4)------ completeWork的工作流程【mount】

    經(jīng)過(guò)上一章,我們得到的FilberNode已經(jīng)具有了child和return屬性。一顆Filber樹(shù)的結(jié)構(gòu)已經(jīng)展現(xiàn)出來(lái)了。 那我們最終是想在頁(yè)面渲染真實(shí)的DOM。所以我們現(xiàn)在要在completeWork里,構(gòu)建出一顆離屏的DOM樹(shù)。 之前在說(shuō)FilberNode的屬性時(shí),我們提到過(guò)一個(gè)屬性stateNode。它就是用來(lái)保存每個(gè)

    2024年02月13日
    瀏覽(26)
  • React源碼解析18(3)------ beginWork的工作流程【mount】

    React源碼解析18(3)------ beginWork的工作流程【mount】

    OK,經(jīng)過(guò)上一篇文章。我們調(diào)用了: 生成了FilberRootNode和HostRootFilber。 并且二者之間的對(duì)應(yīng)關(guān)系也已經(jīng)確定。 而下一步我們就需要調(diào)用render方法來(lái)講react元素掛載在root上: 所以我們現(xiàn)在要實(shí)現(xiàn)ReactDOM.createRoot中返回的render方法。 首先我們思考一下,在React中,除了通過(guò)上面的

    2024年02月13日
    瀏覽(26)
  • React Diff算法

    React Diff算法

    diff算法,是虛擬DOM產(chǎn)生的一個(gè)概念,用來(lái)計(jì)算出虛擬DOM中真正變化的部分,并只針對(duì)該部分進(jìn)行原生DOM操作,而非重新渲染整個(gè)頁(yè)面,從而提高了頁(yè)面的渲染效率。 渲染真實(shí)DOM的開(kāi)銷很大,有時(shí)候我們修改某個(gè)數(shù)據(jù)時(shí),直接渲染到真實(shí)DOM上會(huì)引起整個(gè)DOM樹(shù)的重繪和重排。我

    2024年02月11日
    瀏覽(22)
  • React Diff算法原理

    ??點(diǎn)此(想要了解Diff算法) Diff算法原理 React Diff算法是React用于更新虛擬DOM樹(shù)的一種算法。它通過(guò)比較新舊虛擬DOM樹(shù)的差異,然后只對(duì)有差異的部分進(jìn)行更新,從而提高性能。 React Diff算法的原理如下: 逐層比較:React Diff算法會(huì)從根節(jié)點(diǎn)開(kāi)始逐層比較新舊虛擬DOM樹(shù)的節(jié)點(diǎn)。

    2024年02月11日
    瀏覽(19)
  • 后端程序員入門react筆記——react的diff算法(三)

    后端程序員入門react筆記——react的diff算法(三)

    我們知道,react里面操作的都是虛擬dom,最后經(jīng)過(guò)render渲染為真正的dom,那么為什么要提出虛擬dom這個(gè)概念呢?其實(shí)就是將邏輯和視圖區(qū)分開(kāi),react的虛擬dom,就相當(dāng)于mvc的c,將數(shù)據(jù)邏輯和真正的dom區(qū)分開(kāi),我們知道,對(duì)于前端來(lái)說(shuō)dom操作是非常昂貴的,性能消耗最大的就是

    2024年02月22日
    瀏覽(28)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包