首页 文章

DOMContentLoaded事件中的代码无法正常工作

提问于
浏览
6

我用过

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
</head>
<body>
  <button type="button" id="button">Click</button>
  <pre id="output">Not Loading...</pre>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.17.0/babel.min.js"></script>
  <script type="text/babel">
    document.addEventListener('DOMContentLoaded', function () {
      const button = document.getElementById('button');
      const output = document.getElementById('output');

      output.textContent = 'Loading...';

      addEventListener('click', function () {
        output.textContent = 'Done';
      });
     });
  </script>
</body>
</html>

但似乎 document.addEventListener('DOMContentLoaded', function () {}); 中的代码没有加载 .

如果我从我的代码中删除它,它突然工作 .

我做了一个JS Bin here .

3 回答

  • 24

    在代码挂钩时,事件已经触发了 . Babel standalone的工作方式是通过查找并执行页面上的所有 type="text/babel" 脚本来响应 DOMContentLoaded . 你可以在_498410中看到这个:

    // Listen for load event if we're in a browser and then kick off finding and
    // running of scripts with "text/babel" type.
    const transformScriptTags = () => runScripts(transform);
    if (typeof window !== 'undefined' && window && window.addEventListener) {
      window.addEventListener('DOMContentLoaded', transformScriptTags, false);
    }
    

    只需直接运行代码,无需等待事件,因为您知道Babel standalone会等待它 .

    另请注意,如果您将脚本放在正文末尾,就在结束 </body> 标记之前,即使您不使用Babel,也无需等待 DOMContentLoaded . 脚本上方定义的所有元素都将存在并可供脚本使用 .


    在评论中你问过:

    但是我在开发中使用Babel Standalone,但是在我投入 生产环境 时我会预先编译它 . 我应该在投入 生产环境 时重新添加它吗?

    如上所述,只需确保 script 标记位于 body 的末尾,并且不需要使用该事件 .

    如果你无论如何都要使用它,你可以通过检查document.readyState检查事件是否已经运行(在点击链接后,向上滚动一下):

    function onReady() {
        // ...your code here...
    }
    if (document.readyState !== "loading") {
        onReady(); // Or setTimeout(onReady, 0); if you want it consistently async
    } else {
        document.addEventListener("DOMContentLoaded", onReady);
    }
    

    document.readyState 经历了这些阶段(从上面的链接略微向上滚动):

    文档加载时返回“加载”,完成解析但仍加载子资源后返回“交互”,加载后返回“完成” .

  • 9

    这很可能是因为此时已经触发了 DOMContentLoaded 事件 . 一般的最佳做法是检查document.readyState以确定是否需要监听该事件 .

    if( document.readyState === 'complete' ) {
        console.log( 'document is already ready, just execute code here' );
        myInitCode();
    } else {
        document.addEventListener('DOMContentLoaded', function () {
            console.log( 'document was not ready, place code here' );
            myInitCode();
        });
    }
    
    function myInitCode() {}
    
  • 0

    感谢Ruslan&这里是完整的代码片段,在使用后可以方便地分离 DOMContentLoaded 处理程序 .

    'use strict';
    var dclhandler = false;
    if (document.readyState !== 'loading') {
        start();
    } else {
        dclhandler = true;
        document.addEventListener('DOMContentLoaded', start);
    }
    function start() {
        if (dclhandler) { document.removeEventListener('DOMContentLoaded', start); }
        console.log('Start the site`s JS activities');
    }
    

相关问题