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

資訊專欄INFORMATION COLUMN

自己實現一個簡單的虛擬 DOM

luffyZh / 1390人閱讀

摘要:直到內部的全部循環結束為止,才進入下一個元素,當循環結束時,內部的節點都已經生成好了。

自己實現虛擬 DOM 從 HTML 中提煉數據結構

先來看下我們的 HTML

傅雷家書

讀家書,想付雷

從 HTML 中我們可以抽離出它的數據結構:

首先頁面中只需要一個根節點root,定義為:nodesDate數組

root內有兩個子元素h1span,數組有兩項,每項為內容為tagchildren

接下來內部所有元素都是如此定義,直到遇到文本元素,將他定義為text

nodesDate = {
    tag:"div",
    children:[{
        tag:"h1",
        children:[{
            tag:"span",
            children:[{
                tag:"#text",
                text:"傅雷家書"
            }]
        }]
    },{
        tag:"span",
        children:[{
            tag:"#text",
            text:"讀家書,想傅雷"
        }]
    }]
}

用這種視野在看 HTML 的話,就不是單純的 HTML 了,而是一堆hash

從上面數據結構中我們可以提煉出3個有用的屬性,分別是tagchildrentext,那我們是不是可以定義一個方法,傳遞這三個參數,就能滿足我們的需求呢?

構造 HTML 方法

想一下我們拿到這三個參數后,要干什么呢?

當然是在頁面中生成 DOM 元素啊!

對,這三個參數是我們各自私有屬性,通過這三個屬性能生成各自的 DOM,生成 DOM 的方法是不是公用的呢?

所以可以用用構造函數模式創建我們要的方法,(PS:之前講過new操作符的背后的邏輯,不理解的可移步:使用 new 操作符內部到底在做什么)

function vNode(tag,children,text){
    this.tag = tag
    this.children = children
    this.text = text
}

vNode.prototype.render = function(){
    //如 tag 為文本的話,創建一個文本節點
    if(this.tag === "#text"){
        return document.createTextNode(this.text)    // 返回文本
    }
    
    //tag 不是文本的話,創建一個 DOM 節點,并且遍歷 children,每次遍歷都是調用自身的 render 方法
    let element = document.createElement(this.tag)
    this.children.forEach((vChild)=> {
        element.appendChild(vChild.render())    //在遍歷 h1 時,沒有直接跳出,而是在其內部不斷循環。直到 h1 內部的 children 全部循環結束為止,才進入下一個元素 span,當 h1 循環結束時,h1 內部的節點都已經生成好了。
    })
    return element        //返回節點
}

function v(tag,children,text){
    //如果 chilren 為字符串,那么就把 children 賦值給 text,并把 children 初始化為 [],不然后面會報錯
    if(typeof children === "string"){
        text = children
        children = []
    }
    return new vNode(tag,children,text)
}

//格式參見 nodesData,vNode 的實例化
let vNodes = v("div",[
    v("h1",[
        v("span",[
            v("#text","傅雷家書")])
    ]),
    v("span",[
        v("#text","——傅敏")])
])

const root = document.querySelector(".root")    //獲取 root 節點
root.appendChild(vNodes.render())    //這里只運行一次,把最終的 DOM 添加進頁面中
實現增刪改

如果此時一個數據變動比如,按照以前的邏輯

root.innerText = ""
root.appendChild(vNodes.render())

如果數據非常大,用這種方法根本沒啥意義,每一次改動 DOM 樹都要重新渲染一遍,造成性能低下,有什么好的方法可以實現呢?

function patchElement(parent, newVNodes, oldVNodes, index = 0) {
    //如果沒有傳遞老的 VNodes,默認就是新的
    if(!oldVNodes) {
        parent.appendChild(newVNodes.render())
      } else if(!newVNodes) {
        parent.removeChild(parent.childNodes[index])
      } else if(newVNodes.tag !== oldVNodes.tag || newVNodes.text !== oldVNodse.text) {    
          //如果元素不一樣或者文本不一樣,走這邊
          //當有走這邊時,newVNodes 是和 oldVNodes 不同的那個值,這里的 parent 是當前元素或文本的 parent
          //replaceChild(sp1,sp2),是將 sp2 換成 sp1
        parent.replaceChild(newVNodes.render(), parent.childNodes[index])
      } else {
        for(let i = 0; i < newVNodes.children.length || i < oldVNodes.children.length; i++) {
        //取值永遠是 newVNodes.length,除非不傳 newVNodes
        //這里 index 只有當 i 變化時,下一次才是 index 才等于 i 的值
        //當 i = 0 時,這次的 parent.childNode[index],是下一次的 parent,所以這里要用 index
        //當循環走完,發現元素或者文本不一樣時,才走第三個邏輯
              patchElement(parent.childNodes[index], newVNodes.children[i], oldVNodes.children[i], i)
        }
      }
}

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

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

相關文章

  • 虛擬DOM

    摘要:什么是虛擬舉例說明如果網頁中有一個表格,表頭是姓名,年級,分數。即我們用虛擬的結構替換需要處理的結構,對虛擬的進行操作之后再進行渲染,就成為了真實的數據。當狀態變更的時候用修改后的新渲染的的對象和舊的虛擬對象作對比,記錄著兩棵樹的差異。 虛擬DOM 可以看看這個文章如何理解虛擬DOM? - 戴嘉華的回答 - 知乎 https://www.zhihu.com/questio... 深度剖...

    yanwei 評論0 收藏0
  • 虛擬DOM

    摘要:什么是虛擬舉例說明如果網頁中有一個表格,表頭是姓名,年級,分數。即我們用虛擬的結構替換需要處理的結構,對虛擬的進行操作之后再進行渲染,就成為了真實的數據。當狀態變更的時候用修改后的新渲染的的對象和舊的虛擬對象作對比,記錄著兩棵樹的差異。 虛擬DOM 可以看看這個文章如何理解虛擬DOM? - 戴嘉華的回答 - 知乎 https://www.zhihu.com/questio... 深度剖...

    alin 評論0 收藏0
  • 從零開始實現一個React(一):JSX和虛擬DOM

    摘要:前言是前端最受歡迎的框架之一,解讀其源碼的文章非常多,但是我想從另一個角度去解讀從零開始實現一個,從層面實現的大部分功能,在這個過程中去探索為什么有虛擬為什么這樣設計等問題。 前言 React是前端最受歡迎的框架之一,解讀其源碼的文章非常多,但是我想從另一個角度去解讀React:從零開始實現一個React,從API層面實現React的大部分功能,在這個過程中去探索為什么有虛擬DOM、d...

    曹金海 評論0 收藏0
  • 如何編寫自己虛擬DOM

    摘要:要構建自己的虛擬,需要知道兩件事。現在來看看如何處理上面描述的所有情況。代碼如下節點的替換首先,需要編寫一個函數來比較兩個節點舊節點和新節點,并告訴節點是否真的發生了變化。總結現在我們已經編寫了虛擬實現及了解它的工作原理。 showImg(https://segmentfault.com/img/bVbmPue?w=2000&h=684); 要構建自己的虛擬DOM,需要知道兩件事。你甚...

    mushang 評論0 收藏0

發表評論

0條評論

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