如何在没有 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>

(虽然一般来说,如果这是目的,最好在用脚本元素替换它们时删除后备元素,这样如果一个脚本出错,页面上的所有其他组件都不会中断。)

这是绑定元素的最快方法:在创建元素后立即进行(如果您只需要更改元素,则在打开标签内;如果您需要更改其内容,则在关闭标签之后)。然而,这种方法确实倾向于用丑陋的&lt;script&gt; 块在页面上乱扔垃圾,这就是为什么更多人将代码全部放在底部或使用加载/就绪处理程序的原因。

【讨论】:

【参考方案3】:

放这个

<script>document.body.className += ' javascript';</script>

&lt;/body&gt; 标记之前。简单易行(而且非常接近)的解决方案。

【讨论】:

【参考方案4】:

你有没有尝试在你身体的最末端放置以下内容?

<script>
    document.body.className = 'javascript';
</script>

【讨论】:

【参考方案5】:

如果您想重现 jQuery 的 document.ready 事件,您可以在适用的情况下使用 onreadystatechangeDOMContentLoaded 事件:

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() 行为 [重复]

JQuery没有检测到角度指令中的DOM元素

如何在没有敌人与它们互动的情况下产生能量提升并检测它们何时被拾取

如何检测 DOM 节点插入? [复制]

jQuery 如何获取到隐藏元素的高度?或者在dom元素可见性改变时能触发个事件也行。