将一段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标签来代替

模板结构
  • 1
  • 2
  • 3
  • 4
  • 5

接下来是获取根节点,获取整颗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);

最终渲染出来的效果是这样子的:

将一段HTML转为虚拟DOM再渲染到浏览器上-模拟Vue中的template模板标签_第1张图片

你可能感兴趣的:(JavaScript,前端开发,前端,HTML,JavaScript,DOM)