5

假设您有一个容器 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>

是否会以任何(有意义的)方式为每个单个元素损害(客户端)性能包括一个唯一的 ID,无论是渲染、javascript 还是内存方面?

为什么我要问:我可能需要不时引用特定项目,我试图弄清楚我是否应该提前预先计算我需要选择哪些项目,给它们 id 并将其余的排除在外,或者只是为所有这些分配ID,这将使过程更加直接,但我想知道这是否可能是一种矫枉过正。

如果有人可以谈论现代浏览器如何处理这一点以及为什么它会/不会在浏览器如何呈现和管理 DOM 方面产生影响,那么奖励积分(如果我真的可以给他们的话)。

4

5 回答 5

3

最多,我猜测浏览器会做的几件事就是在构建 DOM 结构时将 ID 作为属性分配给每个元素,并将 ID 存储在哈希表中以方便#id选择器之类的事情,document.getElementById()和 idref 稍后查找。我认为这不会对观察到的性能或内存使用造成轻微影响,因为哈希表和 DOM 设计得非常好。

也就是说,如果您的元素根本不需要 ID 那么为它们分配 ID 毫无意义;相反,您最终会出现大量标记膨胀。正如 Dan Davies Brackett 所提到的,这显然导致速度变慢,因为它取决于客户端连接。

如果您有能力使用 CSS 选择器引用这些元素,则始终可以使用它:nth-child()来查找特定的子元素。如果您需要支持较旧的浏览器,总有一个 CSS2 解决方案。请参阅以下问题:

于 2012-08-07T22:56:56.410 回答
2

正如 BoltClock 所暗示的,大多数性能问题的答案是“测量它!”。也就是说,您错过了一个潜在的衡量轴:下载大小。将 ID 属性添加到比必要更多的元素会增加您的字节权重,尤其是因为元素必须是唯一的(这意味着它们不会像非唯一属性那样压缩)。

于 2012-08-07T23:01:13.527 回答
2

最初的 Q 对内容/目的不是很具体,应该有变化,这取决于 IMO。在某一点上,我绝对不同意当前接受的答案。循环并附加新的 ID 到大量已经渲染的 HTML 可能会导致大量的回流计算,这可能会变得丑陋,具体取决于“stuffContainer”代表什么。

如果必须,首先从服务器使用 ID 构建或在客户端作为单个块注入

作为一般规则,如果可以避免,请避免重复更改 DOM。就加载页面的浏览器 IMO 而言,预先在服务器上构建的 ID 可以忽略不计。当然,它是一个更大的,因此更慢的哈希表,但如果我们谈论的是数百而不是数万,我严重怀疑你会注意到。

对于从数据构建的选择列表之类的情况,一种更有效的客户端方法是首先构建为字符串,带有 ID 和所有内容,然后分配给容器的 innerHTML,或者像我的一些 js 聊天同事一样,您在每个可能的用例中都有一个关于 innerHTML 的奇怪挂断,即使它现在在规范中,至少首先构建并附加到文档片段。然后将其附加到您的容器中。

ID 上的数据属性或类

IMO,气味因素与性能无关,而是 HTML 膨胀和创建不需要的 ID 依赖项,从而阻止其他可能在您的单个项目 div 上找到自定义 ID 有用的东西。ID 绝对是缩小 JavaScript 中元素查找范围的理想方式,但在容器包含内容的情况下,您将从 ID 容器中获得比 ID 为每个子项 ID 更大的灵活性。单步与两步的性能增益不值得将通用 ID 应用于元素的灵活性成本。

作为替代方案,您可以使用具有唯一值或数据属性的类,例如'data-itemId="0"'。对于较小的 HTML 集,例如自定义选择列表,其中 ID 连接到某些服务器端索引系统以便于更新数据,我倾向于使用这种高度可见的方法,因为它更容易理解架构,但它增加了很多在可能涉及数百到数千个项目的情况下跟踪不必要的属性。

或者理想情况下(在大多数情况下),事件委托

最理想的是,IMO,如果您只关心您单击的子单项元素而不是它的“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);
} );
于 2012-09-17T20:11:37.740 回答
1

id即使使用了数百次,使用属性也不会显着降低性能。虽然手动挑选需要唯一标识的元素会稍微快一些,但在我看来,性能改进并不能证明这样做所需的额外时间是合理的。

话虽如此,我不确定id在这种情况下是否需要属性。如果您要使用 jQuery,您可以选择第四个元素,例如,使用以下代码:

$('.single-item').eq(3);
于 2012-08-07T23:00:44.287 回答
0

在这种情况下,在所有东西上使用 id 都会有点过分。我知道您来自哪里,但是如果您使用像 jQuery 这样的语言,考虑到结构,选择子项会很容易。这是一个示例,说明您如何知道单击了哪个 div:

$('.single-item').click(function()
{
    var yourClickedDiv = $(this);
    // execute the rest of your code here
});

这只是一个小例子,但正如您所看到的,您可以访问每个 div 以执行您需要做的任何事情。这将使 html 文件不会因为过多的 id 标签而变得杂乱无章,同时保持文件大小更小一些(更不用说避免生成每个唯一 id 的麻烦了)。

于 2012-08-07T23:03:52.173 回答