Javascript DOMContentLoaded 事件中的代码不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39993676/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 23:07:54  来源:igfitidea点击:

Code inside DOMContentLoaded event not working

javascriptbabeljsaddeventlistenerdomcontentloaded

提问by Jamgreen

I have used

我用过了

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

but it seems the code inside document.addEventListener('DOMContentLoaded', function () {});is not loading.

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

If I remove this from my code, it suddenly works.

如果我从我的代码中删除它,它会突然起作用。

I have made a JS Bin here.

在这里做了一个JS Bin

回答by jAndy

It's most likely because the DOMContentLoadedevent was already fired at this point. The best practice in general is to check for document.readyStateto determine whether or not you need to listen for that event at all.

这很可能是因为此时该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() {}

回答by T.J. Crowder

The event has alreadyfired by the time that code hooks it. The way Babel standaloneworks is by responding to DOMContentLoadedby finding and executing all of the type="text/babel"scripts on the page. You can see this in the index.jsfile:

该事件在代码挂钩它时已经触发。该方法巴贝尔独立的工作原理是通过响应DOMContentLoaded通过查找和执行所有的type="text/babel"脚本的页面上。您可以在index.js文件中看到这一点:

// 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);
}

Just run the code directly, without waiting for the event, since you know Babel standalone will wait for it for you.

直接运行代码,不用等待事件,因为你知道 Babel Standalone 会等你。

Also note that if you put you script at the end of the body, just before the closing </body>tag, there's no need to wait for DOMContentLoadedeven if you don't use Babel. All of the elements defined above the script will exist and be available to your script.

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



In a comment you've asked:

在您问过的评论中:

But I am using Babel standalone in development, but I will pre-compile it when I go into production. Should I add it back on when I go into production?

但是我在开发中使用 Babel Standalone,但我会在投入生产时对其进行预编译。当我投入生产时,我应该重新添加它吗?

Just ensure that your scripttag is at the end of bodyas described above, and there's no need to use the event.

只需确保您的script标签位于上述末尾,body无需使用该事件。

If it's important to you to use it anyway, you can check to see whether the event has already run by checking document.readyState(after following the link, scroll up a bit):

如果无论如何使用它对您来说很重要,您可以通过检查来查看事件是否已经运行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.readyStategoes through these stages (scroll up slightly from the link above):

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

Returns "loading"while the Document is loading, "interactive"once it is finished parsing but still loading sub-resources, and "complete"once it has loaded.

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

回答by Valentine Shi

Thanks to Ruslan & here is the full code snippet with the convenient detach of the DOMContentLoadedhandler after it is used.

感谢 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');
}

回答by JazzBrotha

Another option would be to use the readystatechangeevent. The readystatechangeevent fires when the readyStateattribute of the documenthas changed. The readyStateattribute can be one of the following three values: 'loading', 'interactive', or 'complete'. An alternative to using the DOMContentLoadedevent is to look for the readyStateto equal 'interactive'inside of the document's readystatechangeevent, as in the following snippet.

另一种选择是使用该readystatechange事件。readystatechange当 的readyState属性document发生变化时会触发该事件。所述readyState属性可以是以下三个值之一:'loading''interactive',或'complete'。使用的另一种DOMContentLoaded事件是看为readyState等于'interactive'所述的内部documentreadystatechange情况下,如在下面的代码段。

document.onreadystatechange = function () {
  if (document.readyState === 'interactive') {
    // Execute code here
  }
}

Although, in your case, the document's readyStateseems to have already reached 'complete'. In that case, you can simply swap 'interactive'for 'complete'in the snippet above. This is technically equal to the loadevent instead of the DOMContentLoadedevent.

尽管在您的情况下,document'sreadyState似乎已经达到'complete'. 在这种情况下,你可以简单地换'interactive''complete'在上面的代码片段。这在技术上等于load事件而不是DOMContentLoaded事件。

Read more on MDN, Document.readyStateDocument: readystatechange event

在 MDN 上阅读更多内容, Document.readyState文档:readystatechange 事件

回答by Robin Grgi

I would use document.addEventListener("DOMContentLoaded", () => {/*yourcode*/});

我会用 document.addEventListener("DOMContentLoaded", () => {/*yourcode*/});

回答by Анастасия

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

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
});