gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 20:50:25 26 4
gpt4 key购买 nike

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

正在阅读 how it works under the hood ,这似乎暗示模板和 DOM 之间建立了牢固的联系,我认为这意味着它需要与 VirtualDOM 不同的思维方式来优化性能。

我编写了一些代码来显示使用 hyperHtml 与 normalHtml 对表中的 N 元素进行排序。 normalHtml 版本只是刷新表并重建元素。它们在性能方面似乎相似。我在这里比较苹果和橘子吗?如何使代码的 hyperHtml 版本性能更好?

代码:

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 在我的代码示例中的性能与普通的 DOM 操作一样好,以及我如何才能使 HyperHTML 在重新排序 DOM 节点时性能更高?

最佳答案

更新

hyperHTML 2.14 引入了 domdiff V2 的使用,它带来了类似 petit-dom 的性能,但库的成本增加了 0.6K,希望值得改变。

由于某些奇怪的原因,原始演示在 Safari 上也存在巨大问题,很可能与节点作为 TR 直接附加到 TABLE 而不是附加到表 TBODY 元素这一事实有关。

无论如何,您现在可以比较有线演示的性能 through this CodePen .

请注意所有关于旧的 snabdom 差异的说法也不再相关。


看来您还可以阅读更多内容,到达 the wire part ,因为你得到了 bind 一个。

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

  • 每次您丢弃所有节点并从头开始创建它们
  • 对任何节点的所有引用都将永远丢失
  • GC操作量较高
  • 布局容易发生 XSS,因此不安全

为了避免重复所有这些 innerHTML 陷阱并正确使用 hyperHTML,您需要将 wire 项目连接到这些代表的节点。

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

但是,由于内存是一个问题,电线通过 WeakMap 工作,所以数字,除非用作电线的 :ids,否则不是很好。

现实情况是,在现实世界中没有人将数字或字符串作为项目,它们 99% 的时间都由对象表示,因此为了演示起见,让对象成为对象。

Array.apply(null, Array(numberOfElements)).map(
(el, i) => new Number(i)
)

一旦你有了对象而不是基元,这是我为演示而创建的那种对象,一个更现实的场景,每次你调用渲染或更新时,行都不会被丢弃并且每次都重新创建,这些将被简单地重新排序,正如您在 my CodePen fork 中看到的那样你的,基本上总结如下:

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 后面有 an engine called domdiff其目的是重新组织节点。

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

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

简而言之,虽然普通 DOM 方法线性快速(或缓慢),但算法有最好的情况和最坏的情况。

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

70000 行毫不费力

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

您可以 see an early prototype in this page ,并意识到框架如何处理 10000 个表行并不重要,因为一个好的组件不应该在 DOM 上放置如此多的节点,因为没有用户能够一次看到所有这些节点。

正如您在那个 70K 的表格中看到的那样,排序是一闪而过的,搜索和滚动也是如此,这就是 HyperHTMLElement 的全部荣耀。

These benchmarks ?对于日常的、现实世界的任务来说不是那么有趣。

我希望这能解答您所有的疑问。

关于javascript - 重新排序 DOM 节点时的 HyperHTML 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52203055/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com