注意:使用第 3 方选项卡系统不是一种选择,所以请不要推荐。
在我的页面上,我有几个 <div>
s 和几个选项卡。每个 div 可以属于多个选项卡。例如,所有的 div 都属于“全部”选项卡,然后一些 div 属于“今天”选项卡,一些属于“明天”选项卡,等等。
我想做的是,当用户单击“今日”选项卡时,我只想显示属于该选项卡的 div。当他单击任何其他选项卡时,前一个选项卡的 div 应该被隐藏,而所选选项卡的 div 应该显示。到目前为止非常标准的 Tab 键行为。
但不同的是,一个div可以在多个标签之间共享。
我在想,无论何时选择一个新标签,我都可以简单地遍历最后一个选择的标签的所有 div,隐藏它们,然后循环遍历当前标签的 div 并显示它们。
但是我想知道是否会有更有效/更少 CPU 密集型方法。此外,如果它们在最后一个选项卡和当前选项卡之间共享,此方法将导致某些 div 仅被隐藏然后立即再次显示。 (例如:div_111 可以在 Today 和 Tomorrow 之间共享。用户点击 Today,div_111 显示。然后他点击 Tomorrow,div_111 先隐藏,然后再次显示)。
有什么建议吗?
您要注意的是重绘。当您添加或删除元素时,浏览器必须弄清楚更改如何影响页面上的每个其他元素,并相应地重新定位/调整每个元素的大小。这个过程几乎总是 DOM 操作中最昂贵的部分 - 当然比弄清楚哪些元素放在哪些选项卡中更昂贵。
浏览器会尝试优化重绘 - 它们会尽可能少地重绘页面,有时会将多个更改组合到同一个重绘中。但是,最好将事情掌握在自己手中。无论添加或删除多少节点,您都可以确保重绘不超过两次,方法是首先从 DOM 中删除父节点,然后进行所有更改,然后重新附加它。这是一个简单的例子:
var container = document.getElementById('container'),
buffer = document.createDocumentFragment(),
newNodes = tabs[selection], // an array or object, generated at page load,
// containing all divs that show up in this tab
i, div;
document.body.removeChild(container);
for (i = 0; div = newNodes[i]; i++) {
buffer.appendChild(div); // if div is in container then it will be
// automatically removed
}
container.innerHTML = ''; // probably more efficient to remove nodes individually
container.appendChild(buffer);
document.body.appendChild(container);
根据您的布局,删除 container
可能会导致其下方的内容暂时跳起来。如果您想要优美的外观,您可以修复 container
的父级的高度,或者使用 container.parentNode.replaceNode()
在其位置插入一个占位符。
如果您最大限度地减少重绘,那么您就不会有任何效率问题。但如果您仍然想调整,当然,优化您的内容插入逻辑。做到这一点的最简单方法可能是将绑定(bind)到单个选项卡的内容与显示在多个选项卡中的内容分开,可能通过为每种内容类型使用不同的容器。请记住,最好的解决方案是不要过于普遍化。