什么时候应该使用一个事件监听器?何时应该使用多个事件监听器?

时间:2014-12-30 00:12:23

标签: javascript jquery html events

在这种情况下,当使用事件监听器(使用jQuery)时,我有点混淆什么是最佳选择,性能方面。

案例1 : 假设你有一个包含两个输入的div,你想要"听"同时为 keyUp 事件。 (这个div是文档中唯一的东西,它的高度和宽度也是完整文档的那个)

        <div id=formContainer>
            <input type="text" id="a">
            <input type="text" id="b">
        </div>

什么会更好? :附加&#39;委派的事件监听器&#39;到 formContainer 或将事件监听器附加到每个输入

案例2 : 现在,假设你有一个像这样的html结构(同样,chatContainer是文档的完整高度和宽度,它和它的子节点只是它的内容)

   <div id=chatContainer>

     <div id="menu"></div> //Has to listen to clicks for interactivity
     <div id="messagesWindow"></div> //Has to listen to clicks on every message appended
     <input type="text" id="inputSomething"> //Has to listen to keyUp events

   </div>

在这种情况下,最好将事件监听器附加到每个div /输入或将所有需要的事件监听器附加到 chatContainer(keyUp,click)

我已经阅读了委托活动,但我不知道我是否做对了。即使性能差异很小,我也希望做得更好。 非常感谢你。

1 个答案:

答案 0 :(得分:0)

我也不知道哪个更快(即使差异很小)。所以我写了测试代码

由coffeescript编写的代码

虽然你可以在jsfiddle看到javascript代码,但它们是编译后的代码。

案例1 http://jsfiddle.net/5mnroam3/

(你的问题案例)

<div id=formContainer>
    <input type="text" id="a">
    <input type="text" id="b">
</div>

counterA = counterB = 0
$("#formContainer").click( (e) ->
  switch $(e.target).attr("id")
    when "a"
      counterA++
    when "b"
      counterB++
)
startTime = new Date()
for i in [0...10000]
  $("#a").trigger("click")
  $("#b").trigger("click")
endTime = new Date() - startTime
console.log("listen to container : #{endTime} ms","counterA is #{counterA}","counterB is #{counterB}")

counterA = counterB = 0
$("#formContainer").off("click")
$("#a").click((e) ->
  counterA++
)
$("#b").click((e) ->
  counterB++
)
startTime = new Date()
for i in [0...10000]
  $("#a").trigger("click")
  $("#b").trigger("click")
endTime = new Date() - startTime
console.log("listen to each elem : #{endTime} ms","counterA is #{counterA}","counterB is #{counterB}")

上面的代码正在进行10000次点击&#34;#a&#34;和&#34;#b&#34;并做&#34;反++&#34;每次事件发生时。 在我的macbook(MBP2013mid chrome latest)中,结果是

listen to container : 2224 ms counterA is 10000 counterB is 10000

listen to each elem : 1952 ms counterA is 10000 counterB is 10000

听每个元素都快一点。

案例2 http://jsfiddle.net/fbjyp5yL/

(Case目标元素有一个子元素,这意味着当你监听外部元素时,你必须检查被点击的元素是否将目标元素作为其父元素,因为e.targetthis在事件回调函数总是最可靠的内部元素)

<div id="outer">
  <div id="element1">
    <div class="children1"></div>
    <div class="children2"></div>
  </div>
  <div id="element2">
    <div class="children1"></div>
    <div class="children2"></div>
  </div>
</div>

counterA = counterB = 0

$("#outer").click( (e) ->
  if $(e.target).closest("#element1").length
    counterA++
  else if $(e.target).closest("#element2").length
    counterB++
  else
    console.log("unexpected event")
)
startTime = new Date()
for i in [0...5000]
  $("#element1 .children1").trigger("click")
  $("#element1 .children2").trigger("click")
  $("#element2 .children1").trigger("click")
  $("#element2 .children2").trigger("click")
endTime = new Date() - startTime
console.log("listen to outer : #{endTime} ms",counterA,counterB)

$("#outer").off("click")
counterA = counterB = 0
$("#element1 .children1,#element1 .children2").click( (e) ->
  counterA++
)
$("#element2 .children1,#element2 .children2").click( (e) ->
  counterB++
)
startTime = new Date()
for i in [0...5000]
  $("#element1 .children1").trigger("click")
  $("#element1 .children2").trigger("click")
  $("#element2 .children1").trigger("click")
  $("#element2 .children2").trigger("click")
endTime = new Date() - startTime
console.log("listen to each elem : #{endTime} ms",counterA,counterB)

在这种情况下,我的结果是

listen to outer : 2547 ms 10000 10000

listen to each elem : 2159 ms 10000 10000

因此,侦听外部元素就像情况1一样慢,并且差异大于case1,即使它只是300-400ms到20000次点击。

<强>结论

虽然使用外部元素或每个内部元素之间的差异很小,但是在每个div /输入上监听事件的速度更快。我确定如果有10个或20个内部元素,差异仍然很小。所以选择你喜欢的任何你喜欢的。