首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >重新排序DOM节点时的HyperHTML性能

重新排序DOM节点时的HyperHTML性能
EN

Stack Overflow用户
提问于 2018-09-06 11:26:15
回答 1查看 436关注 0票数 2

我正在努力理解HyperHTML,以及如何从中获得最好的性能。

阅读关于它是如何在引擎盖下工作的的文章,它似乎意味着模板和DOM之间建立了强大的联系,我认为这意味着它需要与VirtualDOM不同的思维方式来优化性能。

我编写了一些代码来显示使用hyperHtml和normalHtml对表中的N个元素进行排序。normalHtml版本只会刷新表并重新构建元素。他们两人的表现似乎是相似的。我在这里比较苹果和橘子吗?如何使代码的hyperHtml版本更好地执行?

代码:

代码语言:javascript
复制
const numberOfElements = 10000
const items = Array.apply(null, Array(numberOfElements)).map((el, i) => i).sort(() => .5 - Math.random())
const sortMethods = [

  () => 0,
  (a, b) => a - b,
  (a, b) => b - a

]

function hyperHtmlTest() {

  const $node = document.createElement('div')
  const $table = document.createElement('table')
  const $button = document.createElement('button')
  const tableRender = hyperHTML.bind($table)

  let sortMethodIndex = 0

  function render () {

    const sortMethod = sortMethods[sortMethodIndex++ % sortMethods.length]

    tableRender`${
      items.concat().sort(sortMethod).map(item => {
        return `<tr><td>${item}</td></tr>`
      })
    }`
  }

  $node.appendChild($button)
  $node.appendChild($table)

  $button.textContent = 'HyperHTml Sort'
  $button.onclick = render  

  return $node

}

function normalHtmlTest() {

  const $node = document.createElement('div')
  const $table = document.createElement('table')
  const $button = document.createElement('button')

  let sortMethodIndex = 0

  function render () {

    const sortMethod = sortMethods[sortMethodIndex++ % sortMethods.length]

    while($table.childNodes.length)
      $table.removeChild($table.childNodes[0])

    const frag = document.createDocumentFragment()

    items.concat().sort(sortMethod).forEach(item => {

      const tr = document.createElement('tr')
      const td = document.createElement('td')

      td.textContent = item
      tr.appendChild(td)

      frag.appendChild(tr)

    })

    $table.appendChild(frag)

  }

  $node.appendChild($button)
  $node.appendChild($table)

  $button.textContent = 'NormalHtml Sort'
  $button.onclick = render  

  return $node

}

document.body.appendChild(hyperHtmlTest())
document.body.appendChild(normalHtmlTest())

或在CodePen

概括这个问题:为什么在我的代码示例中,HyperHTML和普通的ol‘DOM操作一样具有性能,当重新排序DOM节点时,我如何使HyperHTML更具有性能呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-09-07 08:05:54

更新

hyperHTML 2.14介绍了domdiff V2的使用,它为库增加了0.6K的成本,带来了类似于性能的性能,希望值得进行更改。

由于一些奇怪的原因,最初的演示在Safari上也出现了巨大的问题,这很可能与节点作为TR直接附加到表中而不是表TBODY元素有关。

无论如何,您现在可以比较有线演示通过这个CodePen的性能。

请注意,所有所说的关于旧的网罗的区别,也是不相关的。

似乎您可以读得更远一点,达到线材部分,因为您得到了bind的一个。

基本上,如果您使用字符串数组作为内插值,则您所做的操作与类似于innerHTML的操作没有什么不同,具有所有常规的副作用:

  • 每次删除所有节点并从头开始创建它们时
  • 对任何节点的每一个引用都将永远丢失。
  • GC操作的数量更高。
  • 布局易受XSS影响,因此不安全。

为了避免复制所有这些innerHTML问题并正确使用hyperHTML,您需要将wire项放到它们所表示的节点上。

代码语言:javascript
复制
tableRender`${
  items.concat().sort(sortMethod).map(item => {
    return wire(item)`<tr><td>${item.text}</td></tr>`
  })
}`

但是,由于内存问题,连线通过WeakMap工作,因此数字(除非用作有线的:ids )并不大。

现实是,在现实世界中,没有人有数字或字符串作为项目,99%的时间是由对象表示的,所以为了演示,让对象成为对象。

代码语言:javascript
复制
Array.apply(null, Array(numberOfElements)).map(
  (el, i) => new Number(i)
)

一旦有了对象,而不是原语,这与我为演示而创建的对象(更现实的场景)相比,每次调用呈现或更新时,行都不会被破坏和重新创建,这些行将被简单地重新排序,就像您在我的CodePen叉 of yours中看到的那样,基本概括如下:

代码语言:javascript
复制
function hyperHtmlTest() {
  const {bind, wire} = hyperHTML;
  const render = bind(document.createElement('div'));
  let sortMethodIndex = 0;
  return update();
  function update() {
    const sortMethod = sortMethods[sortMethodIndex++ % sortMethods.length];
    return render`
    <button onclick=${update}>HyperHTml Sort</button>
    <table>
      ${items.concat().sort(sortMethod).map(
        item => wire(item)`<tr><td>${+item}</td></tr>`
      )}
    </table>`;
  }
}

关于性能

在hyperHTML后面是一种叫做domdiff的引擎,目的是重新组织节点。

平均而言,domdiff中使用的算法非常快,但在某些情况下,它可能比浏览器一次创建相同布局的速度慢。

您可以很容易地在我的笔中发现,当您从ASC切换到DESC或相反,它比它的普通DOM对应物快5倍,但是当涉及到完全随机的有序列表时,domdiff会做很多检查,而DOM对应方根本不关心,所以它可能会慢一些。

简单地说,虽然普通DOM方法是线性快的(或慢的),但是算法有最好的情况和最坏的情况。

在几乎每一种情况下都表现良好的算法是petit dom使用的算法,但整个逻辑部分有一个对现实世界场景来说没有必要的权重,但对于非真实世界的基准,肯定是令人印象深刻的。

70000行没有汗水

这已经不是什么秘密了,我现在正在开发一个hyperHTML自定义元素,它的目标是通过一个既可排序又可搜索的表处理数十万行。

您可以使用请参阅本页中的早期原型,并认识到框架如何处理10000行表并不重要,因为一个好的组件不应该设置那么多的节点,因为没有一个用户能够同时看到所有这些节点。

正如您在70K表中所看到的,排序是一个闪光灯,搜索和滚动也是如此,这是HyperHTMLElement的光荣之处。

这些基准?对于日常的,真实的世界,任务来说,没那么有趣。

我希望这能回答你所有的疑虑。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52203055

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档