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

时间:2016-10-12 08:14:29

标签: javascript babeljs addeventlistener domcontentloaded

我用过

<!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

8 个答案:

答案 0 :(得分:34)

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

if( document.readyState !== 'loading' ) {
    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() {}

答案 1 :(得分:12)

在代码挂钩时,事件已经已经触发了。 Babel standalone的工作方式是通过查找并执行页面上的所有DOMContentLoaded脚本来响应type="text/babel"。您可以在index.js file

中看到这一点
// 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经历了这些阶段(从上面的链接略微向上滚动):

  

在文档加载时返回"loading",一旦完成解析但仍加载子资源时返回"interactive",并在加载后加"complete"

答案 2 :(得分:0)

感谢Ruslan&amp;这里是完整的代码片段,使用后可以方便地分离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');
}

答案 3 :(得分:0)

另一种选择是使用layout事件。 readystatechange的{​​{1}}属性已更改时,将触发readystatechange事件。 readyState属性可以是以下三个值之一:documentreadyState'loading'。使用'interactive'事件的另一种方法是在'complete'的{​​{1}}事件中寻找DOMContentLoaded等于readyState,如以下代码段所示

'interactive'

尽管在您的情况下,document的{​​{1}}似乎已经达到readystatechange。在这种情况下,您只需在上面的代码段中将document.onreadystatechange = function () { if (document.readyState === 'interactive') { // Execute code here } } 交换为document。从技术上讲,这等于readyState事件,而不是'complete'事件。

详细了解MDN, Document.readyState Document: readystatechange event

答案 4 :(得分:0)

我会使用curl

答案 5 :(得分:0)

https://learnwithparam.com/blog/vanilla-js-equivalent-of-jquery-ready/

function ready(callbackFunc) {
  if (document.readyState !== 'loading') {
    // Document is already ready, call the callback directly
    callbackFunc();
  } else if (document.addEventListener) {
    // All modern browsers to register DOMContentLoaded
    document.addEventListener('DOMContentLoaded', callbackFunc);
  } else {
    // Old IE browsers
    document.attachEvent('onreadystatechange', function() {
      if (document.readyState === 'complete') {
        callbackFunc();
      }
    });
  }
}

ready(function() {
  // your code here
});

答案 6 :(得分:0)

我干净的方法...

if (document.readyState !== 'loading') init()
else document.addEventListener('DOMContentLoaded', init);

function init() {
    console.log("Do it !");
    ...
}

答案 7 :(得分:-1)

我的实时服务器遇到了这个问题。 我的实时服务器在 cloudflare 上运行,带有一些缓存和火箭加载 js。我认为这是导致意外行为的原因。 使用 DOMContentLoaded 时,代码在本地服务器上运行良好,但在 live 上运行不正常。

如果你可以使用jQuery,切换到

jQuery(document).ready(function() {
//code...
})

按预期工作。