【问题标题】:Issues with setTimeout interfering with load event handler [closed]setTimeout 干扰加载事件处理程序的问题[关闭]
【发布时间】:2016-10-15 00:07:31
【问题描述】:

我在<track> 元素上附加了load 事件处理程序。即使在 <track> 已经加载后附加了处理程序,我如何才能确保它被调用?

例如

track.addEventListener('load', function () {
    //this should get called even if the track has already loaded
});

【问题讨论】:

  • 你想要完成什么?
  • 我们的目标是让这个函数与动态添加的内容一起工作。一种情况是,用户在初始文档加载后使用函数 foo
  • 有什么问题?是不是没有添加事件监听器?
  • 这将继续向同一个元素添加事件侦听器。根本不清楚您要解决什么问题。如果元素实际上是<div>,则它们没有加载事件......只有少数特殊元素有
  • 所以事实证明,我在 HTML 中的 元素中遇到了这个问题。我通过使用 track.readyState == 2 并在需要在不同时间加载时在那里加载事件解决了这个问题。你们对div是正确的。我需要更清楚!

标签: javascript dom-events settimeout race-condition


【解决方案1】:

如果在没有附加侦听器时触发事件,则该事件将丢失。希望HTMLTrackElement 有一个readyState 属性,可以检查它以了解加载状态。

这样的事情应该可以工作,它附加处理程序以处理后续加载事件,如果轨道当前已加载,它也会立即调用回调。

function whenLoaded(track, callback) {
    const LOADED = 2;

    track.addEventListener('load', callback);
    if (track.readyState === LOADED) callback();
}

【讨论】:

    【解决方案2】:

    您的代码几乎可以正常工作,如下所示。我只是将事件从加载更改为单击并在 foo 之前添加了功能词。

    function foo(div) {
      div.addEventListener('click', function() {
        console.log('this loads');
      });
    };
    
    
    var div = document.getElementById('main');
      
    setTimeout(function() {
      foo(div);
    }, 1000);
    #main {
      background-color: red;
      width: 100px;
      height: 100px;
    }
    <div id="main"></div>

    【讨论】:

      【解决方案3】:

      注意,如果default 属性未在<track> 元素中设置,load 事件将不会在铬、铬上触发。

      不确定您是要更改现有 <track> 元素的 src 还是将新的 <track> 元素附加到父 <video> 元素?

      下面的方法将一个新的<track> 元素附加到<video> 元素。将src 传递给foo,将load 事件附加到track 元素,然后附加到父<video> 元素,将<track> 元素附加到<video> 元素,然后将src 设置为传递给的变量foo

      window.onload = function() {
      
        // append next `track` element to `video` in 1 seconds
        setTimeout(function() {
          // pass `src`, `label` to set at `track` element
          addTrack("/path/to/resource2", "track 1") 
        }, 1000);
      
        function foo(track, src) {  
          track.addEventListener("load", function() {
            console.log("this loads");
          });
          video.appendChild(track);
          track.src = src;
        };
      
        function addTrack(src, tracklabel) {
          var track = document.createElement("track");
          track.kind = "captions";
          track.srclang = "en";
          track.label = tracklabel;
          // set `default` attribute at `track` element
          track.setAttribute("default", "default");
          // pass `track` element, `src` to set at `track` to `foo`
          foo(track, src);
        }
      
        addTrack("/path/to/resource1", "track 1");
      
      }
      

      【讨论】:

        【解决方案4】:

        来自您的后续评论:

        我们的目标是让这个函数与动态添加的内容一起工作。

        让事件监听器处理动态内容的最佳解决方案是事件委托。您不必担心在添加动态元素后将事件侦听器添加到动态元素,只需将事件侦听器添加到该元素的 parent 中,该父元素已存在于文档中。或者您可以使用祖父母、曾祖父母等。如果没有更具体的元素可以使用,您甚至可以一直使用 body 元素。

        您可以在加载动态内容之前添加此事件侦听器,因为您将它添加到已经存在的元素上。

        当您的事件侦听器被调用时,event.target 是对触发事件的实际元素的引用。因此,您检查它是否是您要实际处理事件的元素之一。

        this question 的答案有一些很好的例子来说明如何使用事件委托。它非常简单,解决了在动态添加的内容上监听事件的所有问题。

        【讨论】:

        • 注意load 事件不会冒泡。您将需要收听捕获阶段。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-13
        • 1970-01-01
        • 1970-01-01
        • 2011-05-16
        相关资源
        最近更新 更多