如何在没有 jQuery 的情况下检测 DOM 并添加一个类?
Posted
技术标签:
【中文标题】如何在没有 jQuery 的情况下检测 DOM 并添加一个类?【英文标题】:How can I detect DOM ready and add a class without jQuery? 【发布时间】:2010-12-20 04:29:22 【问题描述】:我想在不使用 jQuery 的情况下重写这一行,以便可以更快地应用它(在下载 jQuery 库之前)。这条线是...
$(document).ready(function() $('body').addClass('javascript'); );
如果我将它添加到 html
元素中,我可以省略 DOM 就绪部分吗?这样做的一个问题是验证器不喜欢 html
元素上的 class 属性,即使它是用 JS 插入的。
那么,如果没有 jQuery,我将如何重写它?
【问题讨论】:
你需要一个 DOM API,你不能在 vanilla JS 中做到这一点(你不能在 vanilla JS 中做很多事情)。 ;) 您到底想达到什么目标?你想告诉 CSS JavaScript 可用吗?您想使用浏览器特定的事件尽早完成吗?简单的“onload”事件对您有用吗?任何额外的输入都将有助于为您提供正确的答案。 @David:那jQuery是用什么写的? @Tim Down:它是用 JS 编写的……并利用了 DOM API(W3C 和 Microsoft 对浏览器错误进行了调整),所以它不是“香草”(请注意笑脸)。 嘲笑那些不知情的人既不好玩也不酷。我们都去过一次。此外,帮助他理解为什么他的陈述在语义上不完美会比沾沾自喜更有用。 【参考方案1】:如果只是处理现代浏览器,您可以将其放在开头的 body
标记之后。
<script>
document.body.classList.add("javascript");
</script>
【讨论】:
【参考方案2】:如果您的目标是在页面加载时立即将类添加到body
,也许是为了隐藏 no-JS-fallback 元素,您可以立即在 body 标记内执行此操作,而不是等待任何事件:
<body>
<script type="text/javascript">
document.body.className+= ' javascript';
</script>
(虽然一般来说,如果这是目的,最好在用脚本元素替换它们时删除后备元素,这样如果一个脚本出错,页面上的所有其他组件都不会中断。)
这是绑定元素的最快方法:在创建元素后立即进行(如果您只需要更改元素,则在打开标签内;如果您需要更改其内容,则在关闭标签之后)。然而,这种方法确实倾向于用丑陋的<script>
块在页面上乱扔垃圾,这就是为什么更多人将代码全部放在底部或使用加载/就绪处理程序的原因。
【讨论】:
【参考方案3】:放这个
<script>document.body.className += ' javascript';</script>
</body>
标记之前。简单易行(而且非常接近)的解决方案。
【讨论】:
【参考方案4】:你有没有尝试在你身体的最末端放置以下内容?
<script>
document.body.className = 'javascript';
</script>
【讨论】:
【参考方案5】:如果您想重现 jQuery 的 document.ready
事件,您可以在适用的情况下使用 onreadystatechange
或 DOMContentLoaded
事件:
function domReady ()
document.body.className += " javascript";
// ...
// Mozilla, Opera, Webkit
if ( document.addEventListener )
document.addEventListener( "DOMContentLoaded", function()
document.removeEventListener( "DOMContentLoaded", arguments.callee, false);
domReady();
, false );
// If IE event model is used
else if ( document.attachEvent )
// ensure firing before onload
document.attachEvent("onreadystatechange", function()
if ( document.readyState === "complete" )
document.detachEvent( "onreadystatechange", arguments.callee );
domReady();
);
【讨论】:
另见:***.com/questions/2304941/… 为什么要分离 readystatechange 事件? IE8 会触发该事件两次吗?为什么? @Jan 我猜这是从 jQuery 源转录而来的,它还向 window.onload 添加了一个后备侦听器。因此在 jQuery 源代码中,第一次调用回调时需要移除侦听器以避免调用两次,每个事件调用一次。但是由于这段代码不包含该回退,我认为没有必要删除侦听器。但我只是推测。 如果您尝试复制 jQuery 2.x 的行为,它不包括对document.attachEvent
的功能检测,并且始终使用 DOMContentLoaded 事件。 github.com/jquery/jquery/blob/master/src/core/ready.js
@JanDvorak - 一般来说,删除不再需要的侦听器是一种很好的做法,并且对性能有好处。【参考方案6】:
简单:
window.onload = function()
document.body.className = "javascript";
或者在 HTML 中:
<body onload="document.body.className = 'javascript'">...</body>
除非您想区分“onload 之前”和“onload 之后”,否则您可以静态进行:
<body class="javascript">...</body>
【讨论】:
我认为他正在尝试添加该类,以表明启用了 javascript - 因此您的第三个示例不太适用。此外,很确定 DOMReady 在 Load 之前触发(它将等待图像和外部资源) 请随意忽略第三个示例。平心而论,他并没有表明他想要达到什么目的。【参考方案7】:我不知道vanilla JS,但你可以写:
document.getElementsByTagName('body')[0].className += ' javascript';
在页面底部(在关闭 body 标签之前)。
【讨论】:
document.getElementsByTagName('body')[0] === document.body
在关闭 body
之后也可以正常工作。即使在关闭html
【参考方案8】:
window.onload = function()
var elmt = document.getElementsByTagName('body');
if(elmt)
elmt[0].className = 'javascript';
应该这样做。
编辑:更新为通过标签名称而不是 ID 获取元素。
【讨论】:
@David,谢谢提醒。不要做很多 jQuery 所以假设是通过 ID 找到一个元素。 我很确定onload
是在 $(document).ready
之后触发的 - 例如,我认为它正在等待所有图像加载。
document.body 比 gEBTN[0] 更干净(而且速度稍快)。以上是关于如何在没有 jQuery 的情况下检测 DOM 并添加一个类?的主要内容,如果未能解决你的问题,请参考以下文章
jQuery/Javascript 在没有插件的情况下检测操作系统?
如何在没有 JQuery 的情况下模仿跨浏览器 $(document).ready() 行为 [重复]