【问题标题】:Trigger event upon jQuery being loaded加载 jQuery 时触发事件
【发布时间】:2017-09-11 15:26:57
【问题描述】:

我正在合并使用 YouTube iFrame API 和通过设置了 defer 标志的脚本标签加载的 jQuery。必须设置 defer 标志,因为客户拥有完美的 Google 页面洞察分数并希望保持该分数。

YouTube API 在完全加载并准备好使用后,立即调用我定义的函数onYouTubeIframeAPIReady。然后它会在播放器完全加载和渲染后调用onPlayerReady

我希望在此函数中使用 jQuery,但仅在 onPlayerReady 函数中使用 jQuery 会产生竞争条件(希望在调用 onPlayerReady 时 jQuery 库已完成加载)。

我想到一个可行的解决方案是使用 onPlayerReady 函数来设置一个变量,然后再调用一个测试播放器和 jQuery 的函数。另一个函数在 jQuery 准备就绪时设置一个变量并调用相同的测试函数。

我有一些可以工作的代码,但是检查 jQuery 的部分对我来说似乎很乱,并且还引入了少量额外的不必要的延迟。我想知道是否有人知道在 jQuery 可用时运行某些东西的更好方法。基本上,库本身有内置的 jQuery 回调吗?

我目前的代码如下:

var ready = {
    'jquery': false,
    'youtube' false
},
testJQueryLoaded;

testJQueryLoaded = function() {
    if(typeof jQuery == 'undefined') {
        window.setTimeout(function() {
            testJQueryLoaded();
        }, 25);
        return;
    }

    ready.jquery = true;
    postLibraryLoad();
};

testJQueryLoaded();

function onYouTubeIframeAPIReady() {
    // Stuff
};

function onPlayerReady() {
    ready.youtube = true;
    postLibraryLoad();
};

function postLibraryLoad() {
    if(!ready.jquery || !ready.youtube) {
        return;
    }

    // More stuff
};

【问题讨论】:

  • 不,没有这样的事件。但是,您可以通过 javascript 附加脚本标记并监听其事件。

标签: javascript jquery


【解决方案1】:

根据@KevinB 的建议,您可以利用特定<script> 元素的load 事件

<!DOCTYPE html>
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" defer></script>
  <script>
    const dojQueryStuff = (el, params) => this.jQuery(el, params).appendTo("body");
  </script>
  <script>
    document
    .querySelector("script[src$='3.2.1/jquery.min.js']")
    .onload = event => {
      console.log(event.target.src);

      dojQueryStuff("<div>", {
        html: "jQuery version: " + this.jQuery().jquery + " loaded"
      });
     }
  </script>
</head>

<body>
</body>

</html>

【讨论】:

    【解决方案2】:

    我想.ready() 可以。

    $(document).ready(function(){
        ready.jquery = true;
        postLibraryLoad();
    });
    

    你可能知道但是..
    1.这不会在jQuery加载之前抛出执行错误,并且
    2. 这只会在 jQuery 准备好时执行一次。

    所以我想下面的代码可以工作:

    var ready = {
        'jquery': false,
        'youtube': false
    };
    
    $(document).ready(function(){
        ready.jquery = true;
        postLibraryLoad();
    });
    
    function onYouTubeIframeAPIReady() {
        // Stuff
    }
    
    function onPlayerReady() {
        ready.youtube = true;
        postLibraryLoad();
    }
    
    function postLibraryLoad() {
        if(!ready.jquery || !ready.youtube) {
            return;
        }
    
        // More stuff
    }
    

    假设onYouTubeIframeAPIReady()首先在其他地方触发,这段代码应该在youtube准备好或jQuery准备好之后运行postLibraryLoad()最多两次,最终只有在两者都准备好时才运行// More stuff

    编辑:格式
    编辑:添加说明

    【讨论】:

    • 遗憾的是它确实触发了一个错误,同样是由于在加载 jQuery 库时设置了延迟标志&lt;script src="/js/jquery-3.2.1.min.js" defer&gt;&lt;/script&gt; - 这个标志导致(来自 HTML5 规范)“当页面有完成解析”。由于页面洞察力分数对我的客户来说是必不可少的,所有的 javascript 必须在延迟脚本中,或内联。我自己的研究使我相信在延迟文件中包含此代码将在某些浏览器中引入另一个竞争条件:stackoverflow.com/a/10731231/4027341
    • 您的代码也应该异步加载。防止竞争条件的一种(有趣)方法是 holdReady:api.jquery.com/jQuery.holdReady
    • @Scoots 啊,对不起,我完全没有抓住重点。这可能很了不起,但是否可以制作一个包含 jQuery 和您的代码的脚本文件,而不是两个单独的文件?
    • @AlexKlaus 在这种情况下不是 - 不同的页面播放不同的视频,因此需要动态生成 YouTube API 代码。否则很好的解决方案
    【解决方案3】:

    我知道这可能看起来很奇怪,但如果这是您担心的小代码,那么您为什么不将它添加到 jQuery 库中,在底部。并致电onYouTubeIframeAPIReady()。您也可以完全删除这部分ready.jquery = true;

    【讨论】:

    • YouTube API 代码需要是动态的 - 不同的页面播放不同的视频,因此虽然在真空中可能是一个很好的解决方案,但它不适合这里。 +1 虽然
    【解决方案4】:

    我现在有这个确切的问题。我将通过以下方式处理它。

    <script>
    
    // Custom Event Polyfill for IE11
    if ( typeof window.CustomEvent !== "function" ) {
      function CustomEvent ( event, params ) {
        params = params || { bubbles: false, cancelable: false, detail: undefined };
        var evt = document.createEvent( 'CustomEvent' );
        evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
        return evt;
      }
    
      CustomEvent.prototype = window.Event.prototype;
    
      window.CustomEvent = CustomEvent;
    }
    
    </script>
    

    然后在我从服务器而不是通过 Google 执行的 jQuery 文件加载结束时,我添加了这个

    <script>
    
      // Start of jQuery script
      (function (global, factory) {
        // jquery stuff in here
      })( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
        // ALL OF THE jquery CODE IN HERE ....
        return jQuery;
      });
    
      // I Add this at the end.
    
      var jQueryLoadedEvent = new CustomEvent('jQueryLoaded');
      document.dispatchEvent(jQueryLoadedEvent);
    
    </script>
    

    然后我会用这个包装我自己的脚本。

    <script>
      
      document.addEventListener('jQueryLoaded', function (e) {
        (function ($) {
    
          console.log('All of my code in here. Or some of it, I can wrap more code with the same event listener elsewhere.');
          console.log('jQuery version: ', $.fn.jquery);
    
        })(jQuery);
      });
    
    </script>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多