【问题标题】:shrink html help缩小 html 帮助
【发布时间】:2025-11-27 22:00:02
【问题描述】:

我有一个包含 2000 个项目的数组,需要在 html 中显示 - 每个项目都放入一个 div 中。现在,每个项目都可以有 6 个链接可供单击以进行进一步操作。以下是单个项目当前的外观:

<div class='b'>
  <div class='r'>
    <span id='l1' onclick='doSomething(itemId, linkId);'>1</span>
    <span id='l2' onclick='doSomething(itemId, linkId);'>2</span>
    <span id='l3' onclick='doSomething(itemId, linkId);'>3</span>
    <span id='l4' onclick='doSomething(itemId, linkId);'>4</span>
    <span id='l5' onclick='doSomething(itemId, linkId);'>5</span>
    <span id='l6' onclick='doSomething(itemId, linkId);'>6</span>
  </div>
  <div class='c'>
  some item text
  </div>
</div>

现在问题在于性能。我正在使用 innerHTML 将项目设置为页面上的主 div。我的“单个项目”包含的 html 越多,DOM 添加它所需的时间就越长。我现在正在尝试减少 HTML 以使其尽可能小。有没有办法以不同的方式呈现跨度,而不必为每个跨度使用单个跨度?也许使用 jQuery?

【问题讨论】:

  • 这必须在浏览器中完成?您不能安排网络服务器按您的要求提供内容吗?
  • 但我仍然需要使用 innerHTML 或附加来呈现内容。它仍然会很慢。
  • 你能给我们一个数组的简短例子,以便我们为你写一个上帝的答案吗?
  • obj[0] = {Item: "2001", Description: "some desc", InZones: "1,2,3"}; InZones 用于创建跨度。总共总是有 6 个。如果 InZones 中有任何内容,则需要将适当跨度的类更改为“sel”。希望这是有道理的。
  • 您是在循环中为每个跨度添加innerHTML,还是将所有跨度一起添加一次?

标签: html performance dom innerhtml


【解决方案1】:

您应该做的第一件事是通过 jQuery 或其他框架将 onclick 事件附加到 DIV 并让它冒泡,以便您可以使用 doSomething 覆盖所有情况,并且根据您单击的元素,您可以提取项目 ID 和链接 ID。跨度真的需要ID吗?根据您的示例代码,我不知道。此外,也许不是在页面加载时加载链接和项目 ID,而是根据需要通过 AJAX 获取它们。

午餐吃沙拉时我的两分钱, 尼基特

为 vikasde 更新我的头顶。它的语法可能并不完全正确。我在午休。

$(".b").bind( // the class of your div, use an ID , e.g. #someID if you have more than one element with class b
    "click",
    function(e) { // e is the event object
        // do something with $(e.target), like check if it's one of your links and then do something with it.
    }
);

【讨论】:

  • 我尝试通过 ajax 使用按需加载,但是经理们决定他们需要在页面上一次性加载所有这些。如何使用 jQuery 使点击事件冒泡?
【解决方案2】:

如果您设置节点的InnerHtml 属性,则 DOM 必须解释您的 HTML 文本并将其转换为节点。本质上,您在这里运行语言解释器。更多文本,更多处理时间。我怀疑(但不确定)创建实际的 DOM 元素节点会更快,其中包含所有必要的内容嵌套,并将它们挂钩到包含节点。您的“InnerHTML”解决方案在幕后做同样的事情,但还需要额外的工作来理解您的文本。

我也赞同其他人的建议,他说在服务器上而不是通过 JS 在客户端构建所有这些内容可能更经济。

最后,我认为您可以删除spans 的大部分内容。您不需要 ID,也不需要 onclick() 中的参数。调用一个 JS 函数,该函数将确定它是从哪个节点调用的,向上一个节点查找包含的 div 并可能循环包含的节点和/或查看文本以找出 div 中的哪个项目应该回应。您可以让 onclick 处理程序做很多工作——这项工作只在鼠标点击时完成一次,并且不会乘以 2000 倍。它不会花费大量的用户时间。

【讨论】:

  • innerHTML 不被认为比追加更快吗?
  • 好吧,我可以想象正在发生的事情是 vikasde 正在反复做一些像innerHtml = innerHtml + anotherSpan 这样可怕的事情。因此,为了获得 6 个跨度,他有效地构建了 21 个,其中 15 个用于位桶。就性能而言,这肯定是可怕的。在一个不错的浏览器实现中,如果操作正确,附加节点应该会更快。诀窍是在不可见的情况下组装新内容,因此在完成之前不会触发浏览器更新。
  • @Carl:我在 js 中构建行,当我完成整行后,我使用 innerHTML - 我只使用一次。
  • 太糟糕了,这本来是一个简单的优化目标!对于消极的假设,我坚持纠正和鸡蛋面。
  • 我的下一个建议是使用display: none 类创建所有内容,并在完成所有构建后将类切换为可见。如果您的浏览器在每次插入后都在更新,那就是延迟的来源。它还可以解释为什么(如果)你拥有的行越多,它就会越慢。
【解决方案3】:

John Resig 在documentDragmentshttp://ejohn.org/blog/dom-documentfragments/ 上写了一篇博客

我的建议是为每一行创建一个documentDragment,并在创建它时将其附加到 DOM。如果浏览器有任何挂起,一个 timeout 包装每个 appendChild 可能会有所帮助

function addRow(row) {
    var fragment = document.createDocumentFragment();

    var div = document.createElement('div');
    div.addAttribute('class', 'b');

    fragment.appendChild(div);
    div.innerHtml = "<div>what ever you want in each row</div>";

    // setting a timeout of zero will allow the browser to intersperse the action of attaching to the dom with other things so that the delay isn't so noticable
    window.setTimeout(function() { 
        document.body.appendChild(div);
    }, 0);
};

希望对你有帮助

【讨论】:

  • innerHTML 似乎仍然是最快的解决方案:quirksmode.org/dom/innerhtml.html
  • 你说得对,我已经测试了其中几种方法,但该脚本中最重要的是setTimeout。如果您一次添加每一行,则页面在添加其他行时保持交互。另一种方法 - 如果可以的话 - 是添加没有 6 个区域标记的每一行,然后在将它们添加到 DOM 并添加适当的区域标记后再次循环它们 - 基本上以位在视觉上构建页面。跨度>
【解决方案4】:

另一个问题是页面上的内容太多,您的浏览器无法正常处理。我不确定页面的设计是否允许这样做,但是如何将这 2000 行放入具有固定大小的 DIVoverflow: auto 以便用户在页面中获得一个可滚动的窗口?

这不是我作为用户喜欢的,但如果它修复了光标的怪异问题,它可能是一个可以接受的解决方法。

【讨论】:

    【解决方案5】:

    另一种解决方案

    ...关于“页面内容过多”的问题:

    (当您厌倦了这些建议时,请告诉我!)

    如果您可以选择使用嵌入式对象,请说 Java Applet(我的个人喜好,但大多数人不会碰它)或 JavaFX 或 Flash 或 Silverlight 或...

    然后您可以在该技术中显示所有时髦的数据,嵌入到您的浏览器页面中。页面内容与浏览器无关,因此不会让您感到厌烦。

    除了 Java 或其他什么的加载时间之外,这对用户来说可能是透明且不可见的,即(几乎)可以这样做,因此文本似乎显示在页面上,就好像它直接在HTML。

    【讨论】:

    • 我也会考虑这个。我正在努力让我目前的工作方式。
    • 也许你也可以帮我解决这个问题? *.com/questions/1757106/…