我正在努力理解HyperHTML,以及如何从中获得最好的性能。
阅读关于它是如何在引擎盖下工作的的文章,它似乎意味着模板和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和普通的ol‘DOM操作一样具有性能,当重新排序DOM节点时,我如何使HyperHTML更具有性能呢?
发布于 2018-09-07 08:05:54
更新
hyperHTML 2.14介绍了domdiff V2的使用,它为库增加了0.6K的成本,带来了类似于性能的性能,希望值得进行更改。
由于一些奇怪的原因,最初的演示在Safari上也出现了巨大的问题,这很可能与节点作为TR直接附加到表中而不是表TBODY元素有关。
无论如何,您现在可以比较有线演示通过这个CodePen的性能。
请注意,所有所说的关于旧的网罗的区别,也是不相关的。
似乎您可以读得更远一点,达到线材部分,因为您得到了bind的一个。
基本上,如果您使用字符串数组作为内插值,则您所做的操作与类似于innerHTML的操作没有什么不同,具有所有常规的副作用:
为了避免复制所有这些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)
)一旦有了对象,而不是原语,这与我为演示而创建的对象(更现实的场景)相比,每次调用呈现或更新时,行都不会被破坏和重新创建,这些行将被简单地重新排序,就像您在我的CodePen叉 of yours中看到的那样,基本概括如下:
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的光荣之处。
这些基准?对于日常的,真实的世界,任务来说,没那么有趣。
我希望这能回答你所有的疑虑。
https://stackoverflow.com/questions/52203055
复制相似问题