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
Code inside DOMContentLoaded event not working
提问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.
回答by jAndy
It's most likely because the DOMContentLoaded
event 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 DOMContentLoaded
by finding and executing all of the type="text/babel"
scripts on the page. You can see this in the index.js
file:
该事件在代码挂钩它时已经触发。该方法巴贝尔独立的工作原理是通过响应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 DOMContentLoaded
even 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 script
tag is at the end of body
as 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.readyState
goes 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 DOMContentLoaded
handler 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 readystatechange
event. The readystatechange
event fires when the readyState
attribute of the document
has changed. The readyState
attribute can be one of the following three values: 'loading'
, 'interactive'
, or 'complete'
. An alternative to using the DOMContentLoaded
event is to look for the readyState
to equal 'interactive'
inside of the document
's readystatechange
event, as in the following snippet.
另一种选择是使用该readystatechange
事件。readystatechange
当 的readyState
属性document
发生变化时会触发该事件。所述readyState
属性可以是以下三个值之一:'loading'
,'interactive'
,或'complete'
。使用的另一种DOMContentLoaded
事件是看为readyState
等于'interactive'
所述的内部document
的readystatechange
情况下,如在下面的代码段。
document.onreadystatechange = function () {
if (document.readyState === 'interactive') {
// Execute code here
}
}
Although, in your case, the document
's readyState
seems 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 load
event instead of the DOMContentLoaded
event.
尽管在您的情况下,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
});