如何在没有 jQuery 的情况下检测 DOM 就绪并添加类?

IT技术 javascript jquery
2021-03-11 13:50:08

我想在不使用 jQuery 的情况下重写这一行,以便可以更快地应用它(并且在下载 jQuery 库之前)。线路是...

$(document).ready(function() { $('body').addClass('javascript'); });

如果我将它添加到html元素中,我是否可以省去 DOM 就绪部分?这样做的一个问题是验证器不喜欢html元素上的 class 属性,即使它是用 JS 插入的。

那么,如果没有 jQuery,我将如何重写它?

6个回答

如果要重现 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();
    }
  });
}
为什么要分离 readystatechange 事件?IE8 会触发该事件两次吗?为什么?
2021-04-17 13:50:08
如果您尝试复制 jQuery 2.x 的行为,它不包括功能检测document.attachEvent并始终使用 DOMContentLoaded 事件。github.com/jquery/jquery/blob/master/src/core/ready.js
2021-04-30 13:50:08
@JanDvorak - 一般来说,删除不再需要的侦听器是一种很好的做法,并且对性能有益。
2021-05-01 13:50:08
@Jan 我猜这是从 jQuery 源中转录的,它还向 window.onload 添加了一个回退侦听器。所以在 jQuery 源代码中,第一次调用回调时需要移除监听器以避免调用两次,每个事件一次。但是由于此代码不包含该回退,我认为没有必要删除侦听器。但我只是推测。
2021-05-08 13:50:08
2021-05-09 13:50:08

我不知道 vanilla JS,但你可以写:

document.getElementsByTagName('body')[0].className += ' javascript';

在页面底部(在关闭 body 标签之前)。

document.getElementsByTagName('body')[0] === document.body
2021-04-17 13:50:08
关闭后body也会起作用。即使在关闭之后html
2021-05-02 13:50:08

如果您的目标是body在页面加载时立即添加类,也许是为了隐藏 no-JS-fallback 元素,您可以立即在 body 标签内执行此操作,而不是等待任何事件:

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

(尽管一般来说,如果这是目标,最好在使用脚本元素替换它们时删除回退元素,这样如果一个脚本出错,页面上的所有其他组件就不会中断。)

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

window.onload = function() {
   var elmt =  document.getElementsByTagName('body');
   if(elmt){
      elmt[0].className = 'javascript';
   }
}

那应该这样做。

编辑:更新为通过标签名称而不是 ID 获取元素。

我很确定onload是在之后触发的$(document).ready- 例如,我认为它正在等待所有图像加载。
2021-04-18 13:50:08
@David,谢谢提醒。不要做很多 jQuery 所以假设是通过 ID 找到一个元素。
2021-04-21 13:50:08
document.body 比 gEBTN[0] 更干净(并且稍微快一点)。
2021-05-07 13:50:08

简单的:

window.onload = function() {
  document.body.className = "javascript";
}

或者在 HTML 中:

<body onload="document.body.className = 'javascript'">...</body>

除非您想区分“加载前”和“加载后”,否则可以静态进行:

<body class="javascript">...</body>
随意忽略第三个例子。平心而论,他并没有表明他想通过那个实现什么。
2021-04-30 13:50:08
我认为他正在尝试添加该类,以指示启用了 javascript - 因此您的第三个示例不太好。此外,非常确定 DOMReady 在加载之前触发(它将等待图像和外部资源)
2021-05-10 13:50:08