mvvm 使用 fragment 模仿 html的编译

原文链接: mvvm 使用 fragment 模仿 html的编译

上一篇: vue cli3 使用cdn 减少打包体积 在index文件中加入script标签

下一篇: 使用 vue ui 创建 项目 并且安装webpack-bundle-analyzer 插件

MDN

https://developer.mozilla.org/zh-CN/docs/Web/API/DocumentFragment

DocumentFragment ,文档片段 接口,表示一个没有父级文件的最小文档对象。它被作为一个轻量版的 Document 使用,用于存储已排好版的或尚未打理好格式的XML片段。最大的区别是因为 DocumentFragment 不是真实DOM树的一部分,它的变化不会触发 DOM 树的( 重新渲染 ) ,且不会导致性能等问题。

最常用的方法是使用文档片段作为参数(例如,任何 Node 接口类似 Node.appendChild Node.insertBefore ) 的方法),这种情况下被添加(append)或被插入(inserted)的是片段的所有子节点, 而非片段本身。因为所有的节点会被一次插入到文档中,而这个操作仅发生一个重渲染的操作,而不是每个节点分别被插入到文档中,因为后者会发生多次重渲染的操作。

该接口在Web组件中也非常有用: 模板 元素在其 HTMLTemplateElement.content 属性中包含了一个 DocumentFragment 。

可以使用 document.createDocumentFragment 方法或者构造函数来创建一个空的 DocumentFragment.

属性

该接口没有特殊的属性,其属性都继承自 Node ,并补充了 ParentNode 接口中的属性。

ParentNode.children 只读

返回一个实时(live) HTMLCollection ,包含所有属于 DocumentFragment 元素 类型的子对象。

ParentNode.firstElementChild 只读

返回 DocumentFragment 的第一个 Element 类型的子对象,如果没有则返回 null

ParentNode.lastElementChild 只读

返回 DocumentFragment 的最后一个 Element 类型的子对象,如果没有则返回 null

ParentNode.childElementCount 只读

Returns an unsigned long giving the amount of children that the DocumentFragment has.

构造函数

DocumentFragment()

返回空的 DocumentFragment 对象。

方法

该接口继承 Node 的全部方法, 并实现了 ParentNode 接口中的方法。

DocumentFragment.querySelector()

Returns the first Element node within the DocumentFragment , in document order, that matches the specified selectors.

DocumentFragment.querySelectorAll()

Returns a NodeList of all the Element nodes within the DocumentFragment that match the specified selectors.

DocumentFragment.getElementById()

Returns the first Element node within the DocumentFragment , in document order, that matches the specified ID.

简单例子

原始html文档会在两秒后变化,使用fragment 在内存中模仿vdom,然后一次性挂载

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<ul id="ul">
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>

<script>

  setTimeout(
    () => {
      let ul = document.getElementById('ul')

      // 使用fragment 在内存中修改后,在挂载到真实dom,这样比在dom中修改多次要快
      let fragment = document.createDocumentFragment()
      let child
      while (child = ul.firstChild) {
        console.log(child)
        // 结点只能有一个父节点
        // 当父节点变化后,父节点的子节点列表会自动更新,所以不会出现死循环
        fragment.appendChild(child)
      }
      console.log(fragment)

      Array.from(fragment.childNodes).forEach(
        (node) => {
          console.log(node)
          // 如果是元素结点,将结点中文字替换
          if (node.nodeType === Node.ELEMENT_NODE){
            node.textContent = 'aaa'
          }
        }
      )

      ul.appendChild(fragment)
    }, 2000
  )

</script>
</body>
</html>

挂载之后,如果继续更新fragment中的结点,则dom也会实时重新渲染

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<ul id="ul">
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>

<script>

    setTimeout(
        () => {
            let ul = document.getElementById('ul')

            // 使用fragment 在内存中修改后,在挂载到真实dom,这样比在dom中修改多次要快
            let fragment = document.createDocumentFragment()
            let child
            while (child = ul.firstChild) {
                console.log(child)
                // 结点只能有一个父节点
                // 当父节点变化后,父节点的子节点列表会自动更新,所以不会出现死循环
                fragment.appendChild(child)
            }
            console.log('child',fragment.childNodes)
            let tmp = fragment.childNodes[1]
            console.log('tmp',tmp)
            Array.from(fragment.childNodes).forEach(
                (node) => {
                    console.log(node)
                    // 如果是元素结点,将结点中文字替换
                    if (node.nodeType === Node.ELEMENT_NODE) {
                        node.textContent = 'aaa'
                    }
                }
            )

            ul.appendChild(fragment)
            setTimeout(
                () => {
                    console.log(fragment.childNodes);
                    console.log('tmp',tmp)
                    tmp.textContent='aaaaaaaaaaaaaaaaaaa'
                }, 1000
            )

        }, 1000
    )


</script>
</body>
</html>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值