【问题标题】:Element event listener callback not working with custom event元素事件侦听器回调不适用于自定义事件
【发布时间】:2015-01-05 05:28:48
【问题描述】:

元素事件侦听器回调不适用于自定义事件,在以下代码中,将触发文档和窗口事件侦听器,但不会触发元素(在 IE11、FF33 和 Chrome38 上测试,结果相同。)有什么想法吗?我是否滥用了自定义事件?

var el = document.getElementById('some-elem');
el.addEventListener('custom', function (e) {
  console.log("Element got event: " + e.type);
}, false, true);

document.addEventListener('custom', function (e) {
  console.log("document got event: " + e.type);
}, false);

window.addEventListener('custom', function (e) {
  console.log("window got event: " + e.type);
}, false);

var evt = document.createEvent('CustomEvent');
evt.initCustomEvent('custom', true, false);
document.dispatchEvent(evt);
<div id="some-elem"></div>

【问题讨论】:

    标签: javascript custom-events


    【解决方案1】:

    问题是事件永远不会通过元素,您是在document 上触发事件。相反,在元素上触发它:

    var el = document.getElementById('some-elem');
    el.addEventListener('custom', function (e) {
      console.log("Element got event: " + e.type);
    }, false, true);
    
    document.addEventListener('custom', function (e) {
      console.log("document got event: " + e.type);
    }, false);
    
    window.addEventListener('custom', function (e) {
      console.log("window got event: " + e.type);
    }, false);
    
    var evt = document.createEvent('CustomEvent');
    evt.initCustomEvent('custom', true, false);
    el.dispatchEvent(evt); // <=== Change is here
    &lt;div id="some-elem"&gt;&lt;/div&gt;

    你的评论:

    在我的情况下,调度事件的对象与监听对象不同,这是否意味着自定义事件只能在同一个对象上监听(窗口和文档除外)?

    事件必须穿过元素,就像click 必须穿过元素才能被元素上的click 处理程序看到一样。例如,如果您有一个带有事件处理程序的div,并且在div 内部有一个img,并且您在img 上调度了事件,则div 上的处理程序会触发,因为事件会冒泡(因为您使事件能够冒泡):

    var el = document.getElementById('some-elem');
    el.addEventListener('custom', function (e) {
      snippet.log("Element got event: " + e.type);
    }, false, true);
    
    document.addEventListener('custom', function (e) {
      snippet.log("document got event: " + e.type);
    }, false);
    
    window.addEventListener('custom', function (e) {
      snippet.log("window got event: " + e.type);
    }, false);
    
    var evt = document.createEvent('CustomEvent');
    evt.initCustomEvent('custom', true, false);
    document.getElementById("some-span").dispatchEvent(evt); // <=== Change is here
    <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script><!-- snippet.js details: http://meta.stackexchange.com/a/242144/134069 -->
    <div id="some-elem">
      <span id="some-span"></span>
    </div>

    来自the DOM events spec 的这张图表可能有助于描绘这些东西:

    您调用dispatchEvent 的元素是“目标”元素(该图中的深蓝色td)。

    【讨论】:

    • 在我的情况下,调度事件的对象与监听对象不同,这是否意味着自定义事件只能在同一个对象上监听(窗口和文档除外)?很混乱。 :(
    • @eihero:我已经更新了答案以尝试回答该评论。
    • 这是否意味着冒泡事件永远不会通过兄弟元素?
    • @eihero:正确。事件从父级传递到子级(捕获阶段),然后从子级传递到父级(冒泡阶段)。事件永远不会传递给目标的兄弟姐妹。
    猜你喜欢
    • 2021-12-29
    • 1970-01-01
    • 1970-01-01
    • 2019-09-20
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多