假设您有一个包含数百个非常简单的子元素的容器div,如下所示:
<div id="stuffContainer" class="item-container">
<div class="single-item"></div>
<div class="single-item"></div>
<div class="single-item"></div>
<div class="single-item"></div>
<div class="single-item"></div>
<div class="single-item"></div>
[...]
</div>在渲染、javascript或内存方面,为每个元素包含一个唯一的id会以任何(有意义的)方式损害(客户端)性能吗?
问这个问题的原因:我有时可能需要引用特定的项目,我正在尝试弄清楚是否应该预先计算需要选择的项目,给它们提供in并省略其余的,还是只给所有这些项目分配in,这将使过程更直接,但我想知道这是否可能有些夸张。
如果有人能谈论一下现代浏览器是如何处理这件事的,以及为什么在浏览器如何呈现和管理DOM方面会/不会有什么不同的话,我会给你加分(如果我真的能说出来的话)。
发布于 2012-08-08 06:56:56
至多,我猜测浏览器会做的基本事情是在构建DOM结构时将ID作为属性分配给每个元素,并将ID存储在哈希表中,以便于以后进行#id选择器、document.getElementById()和idref查找。我认为这不会对观察到的性能或内存使用量造成哪怕是轻微的影响,因为哈希表和DOM的设计都经过了很好的优化。
也就是说,如果您的元素上根本不需要if,那么为它们分配if就没有意义了;相反,您最终会得到大量膨胀的标记。正如Dan Davies Brackett提到的,这显然会导致速度减慢,因为这取决于客户端连接。
如果您能够使用CSS选择器引用这些元素,则可以始终使用:nth-child()来查找特定的子项。如果您需要支持较旧的浏览器,总会有一个CSS2解决方案。请参阅以下问题:
发布于 2012-08-08 07:01:14
正如BoltClock所暗示的那样,大多数性能问题的答案是“测量它!”也就是说,您遗漏了一个潜在的测量轴:下载大小。向超过必要的元素添加ID属性会增加字节权重,尤其是因为要求元素是唯一的(这意味着它们不会像非唯一属性那样压缩)。
发布于 2012-09-18 04:11:38
最初的Q对于内容/目的并不是非常具体,并且应该有变化,这取决于IMO。有一点我绝对不同意目前公认的答案。循环遍历和附加新的ID到一吨已经呈现的超文本标记语言可能会导致大量的回流计算,这可能会变得丑陋,这取决于'stuffContainer‘代表什么。
首先从服务器使用if构建,如果必须使用,也可以将其作为单个数据块注入客户端
作为一般规则,如果可以避免,请避免重复使用更改来访问DOM。就浏览器加载页面而言,预先在服务器上构建的ID可以忽略不计。当然,它是一个更大的,因此更慢的哈希表,但如果我们谈论的是数百而不是数万,我严重怀疑你是否会注意到。
对于从数据构建的选择列表,一种更有效的客户端方法是首先以字符串的形式构建,使用ID和所有内容,然后分配给容器的innerHTML,或者如果像我的一些js聊天同事一样,您在每种可能的用例中都会对innerHTML有一个奇怪的问题-尽管它现在已经在规范中,至少首先构建并附加到文档片段。然后将其附加到您的容器。
数据- IDs上的属性或类
在我看来,嗅觉因素与性能关系不大,而是与HTML膨胀有关,并在不需要的地方创建一个ID依赖项,从而阻止在某个单项div上找到有用的自定义ID的其他东西。ID绝对是在JavaScript中缩小元素查找范围的理想方法,但是在包含内容的容器中,从ID容器中获得比ID每个子项都灵活得多的灵活性。单步执行与两步执行相比的性能提升不值得将泛型ID应用于元素的灵活性成本。
作为替代,您可以使用具有唯一值或data属性的类,例如‘data-itemId=“0”。对于较小的HTML集,如自定义选择列表,其中I连接到一些服务器端索引系统以便于更新数据,我倾向于使用这种高度可见的方法,因为它更容易理解体系结构,但它添加了许多不必要的属性来跟踪可能涉及成百上千个项的场景。
或理想情况下(在大多数情况下)事件委派
最理想的情况是,如果您只关心所单击的单项元素的子元素,而不关心它的“ID”是还是,则可以完全避免附加属性。这些单项容器将保持静态的顺序,您可以放心地假定位置是有效的ID。或者,另一种可能适用于非静态单项目集的场景是,如果您在一个对象数组中获得了单项目数据,这些数据被打乱,然后用于在用户发起的排序上构建和替换HTML,这将始终将HTML的顺序与其他数据跟踪依赖项绑定在一起。
非Jquery方法(未经测试):
var myContainer = document.getElementById('stuffContainer');
//ignore following indent goof
myContainer.addEventListener('click', function(e){
var
singleItem,
elementOriginallyClicked = singleItem = e.target,
stuffContainer = this;
//anything clicked inside myContainer will trigger a click event on myContainer
//the original element clicked is e.target
//google 'event bubbling javascript' or 'event delegation javascript' for more info
//climb parentNodes until we get to a single-item node
//unless it's already single-item that was originally clicked
while( !singleItem.className.match(/[=\s'"]single-item[\s'"]/g) ){
singleItem = singleItem.parentNode;
}
//You now have a reference to the element you care about
//If you want the index:
//Get the singleItem's parent's childNodes collection and convert to array
//then use indexOf (MDN has normalizer for IE<=8) to get the index of the single-item
var childArray = Array.prototype.slice.apply(stuffContainer.childNodes,[0]),
thisIndex = childArray.indexOf(singleItem);
doSomethingWithIndex(thisIndex);
//or
//doSomethingWithDOMObject(singleItem);
} );或者简单的JQuery委派风格(也是未测试的):
$('#someContainer').on('click','.single-item', function(){
var $_singleItem = $(this), //jq handles the bubble to the interesting node for you
thisIndex = $_singleItem.index(); //also getting index relative to parent
doSomethingWithIndex(thisIndex);
//or
//doSomethingWithJQObject($_thisItem);
} );https://stackoverflow.com/questions/11855242
复制相似问题