【问题标题】:Event.observe inefficient with prototype Javascript, alternatives?Event.observe 使用原型 Javascript 效率低下,替代方案?
【发布时间】:2011-06-17 09:09:56
【问题描述】:

我们有一个包含很多复选框的表格,我们想要调用一些 Javascript 的复选框。 我们使用类似于这个 sn-p 的东西:

addEventObserver(elementId){
        // ($= means 'ends with') this is required for elementIds which are in a table and get prepended with some id
        $$('[id$=:'+elementId+']').each(function(e) {
            Event.observe(e, 'change', function(event) {
                submitAction(something);
            });
        });
}

所以我们在输入框下方添加一个 Javascript 函数调用:

<input type="checkbox" name="somename" id="somePrependedIdsomeId">    
<script type="text/javascript" language="javascript">
                    addEventObserver('someId');
                </script>

这适用于我们的测试环境设置。在生产中,虽然我们有大约 700 个复选框的表格,这会使浏览器/cpu 卡住。

我们使用jsf

【问题讨论】:

    标签: javascript jsf prototypejs dom-events


    【解决方案1】:

    我会放弃为每个复选框添加事件侦听器,而是编写一个附加到容器元素的“智能”事件处理程序。这是一个简单的例子:

    var theDiv = document.getElementById("foo");
    theDiv.onchange = function(e) {
        if (e.target.tagName.toLowerCase() == "input" 
              && e.target.type.toLowerCase() == "checkbox") {
            alert("do something");
        }
    }
    

    演示:http://jsfiddle.net/xFC3A/

    onchange 事件因此被冒泡的容器 div 捕获。附加到 div 的事件可以测试触发事件的元素类型(source/target element depending on the browser)并做出相应的反应。主要优点是:

    1. 只有一个事件处理程序 - 无需浪费时间将处理程序绑定到数百个元素。
    2. 它将继续处理动态添加的元素(通过 AJAX、JS 等)。

    Read more about Event Delegation.

    一些有用的参考:http://www.quirksmode.org/js/events_properties.html

    【讨论】:

    • 也是一个很好的观点。一个事件处理程序与 700 个事件处理程序肯定会提高性能。
    • 只是一个问题... theDiv.onchange 的行为与 Event.observe 相同吗?当涉及到事件时,我只是遇到了与兼容性有关的奇怪行为......例如
    • @Toskan - 你使用的是纯 JS 的原型吗?哪个浏览器?
    • 它在 IE 8 中不起作用...我发现了问题。 IE 8 在事件处理方面非常糟糕。 Onchange 不会被触发(无论多么愚蠢)。另一方面,onclick 会导致某些工作 - 仍然令人失望 - 每次点击都会触发 onclick,即使是在背景上也是如此。
    • @Toskan - 也许尝试将上述内容放入window.onload = function() { //above code here }
    【解决方案2】:

    我不是一个原型骑师(更像是一个 jQuery 人),但一般来说,任何使用属性选择器的选择器都会很慢。如果您在 700 多个项目上运行该选择器,那么您肯定会遇到巨大的减速。

    您还使用 Prototype 的 each() 方法...您可以重写一些东西以使用原生 javascript for() 循环吗?同样,这里指的是 jQuery,但我通过尽可能使用本机 JS 而不是库方法获得了令人难以置信的性能提升。通过删除一堆 jQuery .each() 方法并用本机 for() 循环替换它们,我将 Web 应用程序的速度提高了 20 倍。

    【讨论】:

      【解决方案3】:

      我认为事件委托应该可以帮助你,简单地将 EventHandler 附加到所有复选框的父级

      $('container').observe("change", changeBy);
      
      function changeBy(e){
                      if (e.element().identify() != "container") {
                  doChange(e.element());
              }
      }
      
      function doChange(elem){
        submitAction(something);
      }
      

      标记:

      <div id="container"> <input type="checkbox" > ... </div>
      

      你不需要做foreach,也没有数百个事件处理程序,你只需一个事件处理程序,这非常快。

      【讨论】:

        【解决方案4】:

        Prototype 已经通过Event.on 提供事件委托:

        $('id_of_table').on('change', 'input[type=checkbox]', some_handler_function);
        

        【讨论】:

        • 我听说 IE 在冒泡事件(委托所依赖的)方面表现不佳,因此这可能不起作用。我没有明确测试过。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-19
        • 2011-01-20
        • 2012-02-02
        • 1970-01-01
        • 2014-05-04
        • 1970-01-01
        相关资源
        最近更新 更多