將一段HTML轉爲虛擬DOM再渲染到瀏覽器上-模擬Vue中的template模板標籤

在我的上一篇文章中,很清晰的講述瞭如何實現虛擬DOM,實現完了以後我就想到了在Vue當中,有template這個模板標籤,我們在真實開發中,不可能是像寫虛擬DOM那樣去描述一個頁面的UI結構,我們還是希望寫的是正常的HTML代碼,這樣纔能有可讀性和維護性。

// 我們不會以這種形式去寫HTML
  let a = h('ul', { id: 'ol-list' }, ['123123',
      h('li', { class: 'item1', style: "list-style: none" }, ['Item1']),
      h('li', { class: 'item2', id: 'li2', style: "color: pink", onclick: 'printStr ()' }, ['Item2']),
      h('li', { class: 'item3', onclick: 'alert(1234)' }, ['Item3'])
    ]).render()

所以在實現了虛擬DOM後,我就在思考如何將一段HTML轉換爲虛擬DOM,這樣既能方便開發,也能爲接下來的研究diff算法起到一定幫助,最後通過使用dom節點的屬性實現了這個過程。接下來就直接講述代碼了,這裏不再重複如何實現Virtual DOM,不知道如何實現的朋友可以查看我的上篇文章如何實現Virtual DOM

整理下思路:

  1. 首先我們通過DOM API獲取到根節點,對它的標籤名、標籤屬性、子節點進行解析。
  2. 通過vnode.tagName屬性拿到標籤名,使用Object.entries函數解析標籤屬性,通過vnode.childNodes屬性拿到子節點並轉爲數組。
  3. 將上述三個參數傳入CreateEl類中,生成虛擬DOM,再調用render方法渲染到瀏覽器中去。

下面就是代碼部分:

首先定義好一段HTML模板代碼,這裏暫時還是以div標籤來代替

<div id="template">
    模板結構
    <ul>
      <li>1</li>
      <li>2</li>
      <li>3</li>
      <li>4</li>
      <li>5</li>
    </ul>
  </div>

接下來是獲取根節點,獲取整顆DOM Tree的所有信息,最後返回一顆虛擬DOM Tree:

// 將dom樹節點劫持到對象中中進行解析 
    function nodeToObject(vnode) {
      let parseProps = {}
      // 定義一個parseProps接收節點屬性 
      for (let [key, val] of Object.entries(vnode.attributes)) {
        parseProps[val.name] = val.value
      }
      let dealChildren = []
      // 定義一個數組接收節點的所有子節點,對於元素則遞歸調用nodeToObject方法
      let parsrChildren = Array.from(vnode.childNodes)
      parsrChildren.forEach((ele) => {
        if (ele instanceof Element) {
          dealChildren.push(nodeToObject(ele))
        } else {
          dealChildren.push(ele.nodeValue)
        }
      })
      let flag = {
        tag: vnode.tagName.toLowerCase(),
        props: parseProps,
        children: dealChildren
      }

      // 返回一個虛擬Dom Tree
      return h(flag.tag, flag.props, flag.children)
    }

這個時候就大公告成了,我們能夠解析傳入的標籤中所有的信息,並將它渲染成真實DOM Tree並渲染到瀏覽器上:

let AST = nodeToObject(document.getElementById('template')).render();
document.body.appendChild(AST);

最終渲染出來的效果是這樣子的:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章