在 IE 上聚焦和/或选择一个输入元素很慢,在 dom 中有大量输入标签

Posted

技术标签:

【中文标题】在 IE 上聚焦和/或选择一个输入元素很慢,在 dom 中有大量输入标签【英文标题】:Focussing and/or selecting an input element slow on IE with large count of input tags inside the dom 【发布时间】:2012-01-08 22:38:19 【问题描述】:

我的公司提供的 ERP 解决方案依赖于使用 IE,因为几年前的一些错误决定(使用动态 html 的行为),所以我无法使用其他浏览器。现在它仅限于IE8。大约有 40.000 个安装在现场......

问题:

通常,我们应用程序中的一个页面在 dom 中有大约 150 - 200 个输入标签。通过 javascript 使用它们没有问题。

但是:现在我们有一个页面(仅针对单个客户),其中包含一个巨大的表格(大约 1500 个表格行),其中每行在某些列中包含大约十个(可编辑)输入字段,因此我们有大约 15000 个输入标签在dom里面。此单页使用 jQuery,该产品的其余部分未使用。

首先:滚动表格(在 div 内)在 IE 上非常慢(占用所有 CPU)。

第二个(也是我现在最关心的问题):如果我想改变焦点和/或选择一个输入标签内的文本,IE 会慢下来。

例如,如果我有一个只有 50 行的表,一切正常,但 IE 会减慢更多行和添加的输入字段。如果我只在表格单元格中放文字信息,IE 是没有问题的。

所以确实是输入字段导致速度变慢,但是有什么办法可以解决这个问题吗?

我愿意接受建议 - 我曾尝试使用可编辑的 div,但我无法让它们 100% 模拟单行输入字段(我需要 onblur 事件、单击事件等)。 目前我也在考虑让产品的这个单页兼容 Chrome,并使用 IE 的 Chrome Frame 插件来显示页面

仅供参考:除了 onblur 事件之外的所有事件都在表格元素上注册。一旦用户单击输入字段(并且最后一个活动行的 onblur 事件被删除),onblur 元素就会在一行内的所有输入字段上注册。

感谢大家分享一些想法...

更新 我已更改代码,以便表格内没有输入字段。只有在一行被激活后,具有可编辑内容的单元格才会获得一个输入元素。 这些输入单元的添加/删除相当快(20 - 40 ms),但选择和关注字段的问题仍然存在...... 对于一个有 190 行的表格,IE 在表格内的输入元素上执行“.focus()”和“.select”大约需要 1600 - 2100 毫秒。 我束手无策——现在我考虑让这个单页与 IE 以外的其他浏览器兼容,并告诉我们的客户安装 Chrome Frame 插件。或者另一种解决方案是为此目的编写一个富客户端 - 所有这些都将花费比支付的更多时间...... 请记住,只要表格内没有太多行,表格布局就可以正常工作...

代码:

表格行示例:

  <tr id="POS_5096" class="ROWSELECTED" poscount="0" ordnernr=
  "ROOT" timestamp="00000000003091FB">
    <td>
      <input class="CHECKONE" type="checkbox" name="wn_folder_dnd">
    </td>
    <td name="FOLDERPATH" dttype="string" dbvalue="002">
      <a href=
      "../Sales/AuftragPosRec.aspx?auftrag=200146&amp;accessID=5096"
      target="_blank">002</a>
    </td>
    <td>
      <input class="CHECKONE" title="Textposition" disabled type="checkbox"
      name="TEXTPOS" dttype="i2" dbvalue="0">
    </td>
    <td>
      <img name="taketextpos" src="../Style/MenuIcons/down.gif">
    </td>
    <td>
      <input class="CHECKONE" title="Durch Mehrung / Minderung verändert"
      disabled type="checkbox" name="WN_MMCHANGED" dttype="i2" dbvalue="0">
    </td>
    <td sizcache="0" sizset="0">
      <input style="TEXT-ALIGN: right; WIDTH: 140px" value=
      "dfgdfgdfgdfnbndfs" name="NAME" dttype="string" dbvalue=
      "dfgdfgdfgdfnbndfs" jquery16409152079553898877="55">
    </td>
    <td>
      <img name="takename" src="../Style/MenuIcons/down.gif">
    </td>
    <td name="NAMEINTERN" dttype="string" dbvalue="PDW-1500 PDW-1500">
      <a href="../Masterdata/ArtikelInfoRec.aspx?artikel=114080" target=
      "_blank">PDW-1500 PDW-1500</a>
    </td>
    <td title="04020asasa" name="ARTIKELGRUPPE" dttype="string" dbvalue=
    "04020">
      04020
    </td>
    <td sizcache="0" sizset="1">
      <input style="TEXT-ALIGN: right; WIDTH: 35px" title="04" value="04"
      name="RABATTGRUPPE" dttype="string" dbvalue="04"
      jquery16409152079553898877="56">
    </td>
    <td>
      <img name="pickrabattgruppe" src="../Style/fieldicons/picklist.gif">
    </td>
    <td>
      <img name="takerabattgruppe" src="../Style/MenuIcons/down.gif">
    </td>
    <td name="HERSTELLER" dbvalue="103736.001">
      <img title="Sony Europe Limited (B)" name="popupadresse()" src=
      "../Style/field-icons/goto-this-dataset.png">
    </td>
    <td name="LIEFERANT" dbvalue="">
      <img title="" name="popupadresse()" src=
      "../Style/field-icons/goto-this-dataset.png">
    </td>
    <td>
      <img name="pickwn_lieferant" src="../Style/fieldicons/picklist.gif">
    </td>
    <td sizcache="0" sizset="2">
      <input style="TEXT-ALIGN: right; WIDTH: 50px" value="2,00" name=
      "MENGE" dttype="number" dtscale="2" dbvalue="2.00"
      jquery16409152079553898877="57">
    </td>
    <td>
      <div style=
      "BORDER-BOTTOM: #809db7 1px solid; BORDER-LEFT: #809db7 1px solid; WIDTH: 10px; BORDER-TOP: #809db7 1px solid; BORDER-RIGHT: #809db7 1px solid"
      name="WN_AUFWAND_BEISTELL" dbvalue="" clickevent="pickbeistell">
         
      </div>
    </td>
    <td sizcache="0" sizset="3">
      <input style="TEXT-ALIGN: right; WIDTH: 55px" name="PREISME" dttype=
      "string" dbvalue="Stück" disabledvalue="Stück"
      jquery16409152079553898877="58">
    </td>
    <td>
      <img name="pickpreisme" src="../Style/fieldicons/picklist.gif">
    </td>
    <td>
      <img name="takepreisme" src="../Style/MenuIcons/down.gif">
    </td>
    <td style="TEXT-ALIGN: right" name="WN_UVP" dttype="number" dtscale="2"
    dbvalue="0.00">
      0,00
    </td>
    <td sizcache="0" sizset="4">
      <input style="TEXT-ALIGN: right; WIDTH: 105px" value="0,00" name=
      "WN_EKPREIS" dttype="number" dtscale="2" dbvalue="0.00"
      jquery16409152079553898877="59">
    </td>
    <td>
      <img name="takewn_ekpreis" src="../Style/MenuIcons/down.gif">
    </td>
    <td sizcache="0" sizset="5">
      <input style="TEXT-ALIGN: right; WIDTH: 30px" name="WN_EKWAEHRUNG"
      dttype="string" dbvalue="USD" disabledvalue="USD"
      jquery16409152079553898877="60">
    </td>
    <td>
      <img name="pickwn_ekwaehrung" src="../Style/fieldicons/picklist.gif">
    </td>
    <td>
      <img name="takewn_ekwaehrung" src="../Style/MenuIcons/down.gif">
    </td>
    <td sizcache="0" sizset="6">
      <input style="TEXT-ALIGN: right; WIDTH: 45px" value="1,00" name=
      "WN_EK_SONDERRABATT" dttype="number" dtscale="2" dbvalue="1.00"
      jquery16409152079553898877="61">
    </td>
    <td>
      <img name="takewn_ek_sonderrabatt" src="../Style/MenuIcons/down.gif">
    </td>
    <td sizcache="0" sizset="7">
      <input style="TEXT-ALIGN: right; WIDTH: 45px" value="0,00" name=
      "WN_EK_SONDERRABATT2" dttype="number" dtscale="2" dbvalue="0.00"
      jquery16409152079553898877="62">
    </td>
    <td>
      <img name="takewn_ek_sonderrabatt2" src=
      "../Style/MenuIcons/down.gif">
    </td>
    <td style="TEXT-ALIGN: right" name="WN_EKPREIS_FINAL" dttype="number"
    dtscale="2" dbvalue="0.00">
      0,00
    </td>
    <td style="TEXT-ALIGN: right" name="WN_AUFSCHLAG" dttype="number"
    dtscale="2" dbvalue="10.00">
      10,00
    </td>
    <td style="TEXT-ALIGN: right" name="MARGE" dttype="number" dtscale="2"
    dbvalue="100.00">
      100,00
    </td>
    <td style="TEXT-ALIGN: right" name="WN_AUFSCHLAGREAL" dttype="number"
    dtscale="2" dbvalue="0.00">
      0,00
    </td>
    <td sizcache="0" sizset="8">
      <input class="CHECKONE" type="checkbox" name="WN_EKFIX" dttype="i2"
      dbvalue="0" clickevent="dataChange">
    </td>
    <td>
      <img name="takewn_ekfix" src="../Style/MenuIcons/down.gif">
    </td>
    <td sizcache="0" sizset="9">
      <input style="TEXT-ALIGN: right; WIDTH: 105px" value="0,00" name=
      "NETTO" dttype="number" dtscale="2" dbvalue="0.00"
      jquery16409152079553898877="63">
    </td>
    <td sizcache="0" sizset="10">
      <input style="TEXT-ALIGN: right; WIDTH: 35px" value="0,00" name=
      "RABATT" dttype="number" dtscale="2" dbvalue="0.00"
      jquery16409152079553898877="64">
    </td>
    <td>
      <img name="takerabatt" src="../Style/MenuIcons/down.gif">
    </td>
    <td sizcache="0" sizset="11">
      <input style="TEXT-ALIGN: right; WIDTH: 35px" value="0,00" name=
      "RABATT2" dttype="number" dtscale="2" dbvalue="0.00"
      jquery16409152079553898877="65">
    </td>
    <td>
      <img name="takerabatt2" src="../Style/MenuIcons/down.gif">
    </td>
    <td sizcache="0" sizset="12">
      <input style="TEXT-ALIGN: right; WIDTH: 35px" value="0,00" name=
      "RABATT3" dttype="number" dtscale="2" dbvalue="0.00"
      jquery16409152079553898877="66">
    </td>
    <td>
      <img name="takerabatt3" src="../Style/MenuIcons/down.gif">
    </td>
    <td sizcache="0" sizset="13">
      <input style="TEXT-ALIGN: right; WIDTH: 35px" value="0,00" name=
      "WN_MARKUP" dttype="number" dtscale="2" dbvalue="0.00"
      jquery16409152079553898877="67">
    </td>
    <td>
      <img name="takewn_markup" src="../Style/MenuIcons/down.gif">
    </td>
    <td style="TEXT-ALIGN: right" name="WN_MARKUPPREIS" dttype="number"
    dtscale="2" dbvalue="0.00">
      0,00
    </td>
    <td style="TEXT-ALIGN: right" name="WN_GESAMTRABATT" dttype="number"
    dtscale="2" dbvalue="0.00">
      0,00
    </td>
    <td style="TEXT-ALIGN: right" name="STKERLOES" dttype="number" dtscale=
    "2" dbvalue="0.00">
      0,00
    </td>
    <td style="TEXT-ALIGN: right" name="DECKUNG" dttype="number" dtscale=
    "2" dbvalue="0.00">
      0,00
    </td>
    <td style="TEXT-ALIGN: right" name="ERLOES" dttype="number" dtscale="2"
    dbvalue="0.00">
      0,00
    </td>
    <td sizcache="0" sizset="14">
      <input style="TEXT-ALIGN: right; WIDTH: 35px" value="0,00" name=
      "MRABATT" dttype="number" dtscale="2" dbvalue="0.00"
      jquery16409152079553898877="68">
    </td>
    <td>
      <img name="takemrabatt" src="../Style/MenuIcons/down.gif">
    </td>
    <td sizcache="0" sizset="15">
      <input style="TEXT-ALIGN: right; WIDTH: 35px" value="0,00" name=
      "RABATT4" dttype="number" dtscale="2" dbvalue="0.00"
      jquery16409152079553898877="69">
    </td>
    <td>
      <img name="takerabatt4" src="../Style/MenuIcons/down.gif">
    </td>
    <td name="USERPOS" dttype="string" dbvalue="21">
      <a href=
      "../Sales/AuftragPosRec.aspx?auftrag=200146&amp;accessID=5096"
      target="_blank">21</a>
    </td>
    <td style="DISPLAY: none" name="TEXT"></td>
    <td style="DISPLAY: none" name="SORTIERUNG">
      a
    </td>
    <td style="DISPLAY: none" name="HERSTELLERNAME">
      Sony Europe Limited (B)
    </td>
    <td style="DISPLAY: none" name="LIEFERANTNAME"></td>
    <td style="DISPLAY: none" name="POSITION">
      21
    </td>
    <td style="DISPLAY: none" name="ARTIKEL">
      114080
    </td>
    <td name="WN_ORDNERNAME"></td>
    <td style="DISPLAY: none" name="WN_LIEFERANT"></td>
    <td style="DISPLAY: none" name="WN_MARKE"></td>
  </tr>

【问题讨论】:

您是否将 jQuery 每个循环绑定到所有输入?如果是这样,你最好使用 javascript for 循环,性能比 jquery 的 each 快 91% 我同意 Jamie 的观点,也尝试将事件绑定到每个 TR 标签而不是表格。 jQuery 必须搜索每一行以找到接收事件操作的字段。在这种情况下,可能值得将处理程序多次绑定到每个 TR 标签,而不是一次绑定到 TABLE。通常这不是真的......但它在这里可能会有所帮助。 John 的评论也是正确的,在 jQuery 中说 $('table').find('tr') 实际上比 $('table tr') 更快,因为 CSS 选择器向后移动: ) 我没有在桌子上使用任何 jQUery“海量处理”。事实上,只是表格本身的呈现(=滚动)很慢,并且输入标签内的文本的聚焦/选择。我已经使用 MS 自己的建议来更快地呈现表格(TABLE-LAYOUT:固定,并设置每列的宽度),这似乎没有帮助(但也没有害处)。 而且,顺便说一下,由于 mouseclick 是在表格上而不是在下一个输入元素上触发的,所以我只需查看事件对象内部即可在单击期间获取 mousepointer 下的 dom 元素事件,所以这里也没有 jQuery 搜索。这不是需要时间,而是对 .focus 和 .select 的函数调用 【参考方案1】:

除了 HTML 之外没有看到脚本,我只能建议两件事:

1) 简介,简介,简介。要么使用更好的浏览器(Chrome/Safari+Devtools 或 Firefox+Firebug 可以提供帮助),要么尝试使用一些 MS 的开发工具(我没有使用这些进行分析的经验,但据我记得 MS 的脚本调试器可以做到这一点) 或DynaTrace,我发现它非常适合使用 IE。找出慢的地方,然后修复它。

2) 去掉所有输入框,点击后将单元格转换为输入框。在 jQuery 中,为此使用委托。大致如下:

$('table').delegate('td', 'click', function() 
    // Switch back and forth between input and text here.
);

这应该可以消除脚本的几乎所有减速。我对 cme​​ts 中声称 jQuery 必须“搜索”模糊的元素持怀疑态度——据我所知,这应该在事件对象上可用。我不明白为什么 jQuery 必须搜索它——但也许我错过了一些东西。

【讨论】:

事实上,使用这样的委托会使一切变得更慢。这就是为什么我只是简单地注册表格元素上的点击,然后检查事件模型以了解真正点击了表格的哪个元素。但是你所说的将简单的文本数据交换为我昨天开始尝试的真实输入字段,但仍然需要一些工作。 我已经分析了慢速选择事件,它确实是 .focus 或 .select 调用减慢了一切(在我的实验表上,找到正确输入单元格的所有代码,保存数据以前选择的单元格进入数据库大约需要 50 - 200 毫秒,而下面的 .focus 和 .select 调用需要 1600 - 2300 毫秒) 好的,你怎么做'(并且最后一个活动行的 onblur 事件正在被删除)。部分?你有参考那个方便还是你在循环?同样,显示实际代码会有所帮助... 实际代码受版权保护,大约 10000 行长(4000 客户端/6000 服务器端)。它还提供了有关我们客户的提示,所以我不得不重写很多。 onblur 事件的删除如下:$("#POS_" + highlightRow.LAST).removeClass("ROWSELECTED").find("input:enabled").unbind("blur"); 这大约需要 2 - 7 毫秒,它确实是 .focus 和 .select 调用对“杀死”IE 的下一行的单击输入元素... Mhhm,我不太了解 cmets 中的代码格式...??? 页面上是否还有其他被触发的选择/焦点处理程序?既然您已经按照更新的建议更改了页面,我真的不确定还有什么可以尝试的。唯一可能仍然对您有所帮助的是知道 jQuery 特殊情况会模糊/聚焦,因此它们会冒泡。您可以尝试调用“真正的”DOM 焦点方法并手动触发任何所需的事件处理程序,看看是否可以解决任何问题?

以上是关于在 IE 上聚焦和/或选择一个输入元素很慢,在 dom 中有大量输入标签的主要内容,如果未能解决你的问题,请参考以下文章

如何在 IE 中动态生成的剔除模板中自动聚焦到输入元素

如何将光标聚焦在条纹输入元素上

Highcharts 鼠标跟踪/鼠标悬停功能在 chrome 上很慢,但在 Firefox 或 IE 上并不慢

当输入集中在移动 safari 上时,页面底部出现不需要的填充

聚焦并选择输入移动

在 iOS8 Safari 中,只读输入处理不正确