jQuery 的 ready()的纯js替代方法
ready方法是jQuery实现的在html页面在DOM(DocumentObjectModel,文档对象模型)树完全加载完成后触发的一个方法.因为它接收的方法在页面中所有的DOM都可访问时才执行,所以此时你完全可以访问和操作html中的元素.
在jQuery3.0之前,典型的匿名函数方式的用法如下:
$(document).ready(function(){ //在.ready()被触发时执行. });
在jQuery3.0中ready()的变化
在jQuery3.0发布之前,有以下几种ready方法的使用方式:
在document对象上:$(document).ready(handler);
在一个空元素上:$().ready(handler);
或直接使用(即:不在一个指定的元素上):$(handler);
以上的几种方式是等价的.传入的handler会在页面所有的DOM都加载完成后执行,不管它被哪个指定元素执行.也就是,在image元素$("img")与document对象上调用ready方法不表明要等待这些元素加载完成后就触发handler,而是在整个DOM树加载完成后才触发.
在jQuery3.0中,除了$(handler);方法其它的都被弃用了.官方的理由是:
因为这个选择与.ready()方法的行为没有关系,它是低效的并且会误导用户猜测这个方法的行为.
Ready和Load事件的不同点
ready事件在页面DOM完全加载后触发并能正确的访问到元素.而load事件在页面DOM及资源文件(图片,视频等)都加载完成后才触发.
load事件可以像下面这样使用:
$(window).on("load",function(){ //当页面所有资源(图片,视频等)全加载完成后才加载执行 });
这会等待DOM加载完成以及图片加载完成(根据图片的大小,需要加载一定的时间).
对于常规的DOM操作你多半不需要load事件,但如果你想做一个等待页面所有资源加载的一个加载效果或者是计算图片的大小时这应该是一个不错的选择.
你可能并不需要jQuery.ready()
ready方法确保了其内部的代码都能正确的操作DOM元素.这是什么意思?当你把JavaScript代码放到HTML文档中时它会确保回调函数里面的代码在浏览器在已经加载页面中所有的元素时执行:
<!doctypehtml> <html> <head> <metacharset="utf-8"> <title>.ready()教程</title> <scriptsrc="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script> <script> $(function(){//.ready()的回调方法,在DOM完全加载完后执行 varlength=$("p").length; //下面会在console控制台中输出1,表示有段落p存在. //这就证明了这个回调方法在DOM完全加载完后执行. console.log(length); }); </script> </head> <body> <p>I'mthecontentofthiswebsite</p> </body> </html>
如果你把要执行的JavaScript放到body元素里面的最后位置,你就不需要用ready()方法把代码包裹在里面了,因为在JavaScript代码执行时页面中所有的元素都已经加载完成,所以此时你就可以访问或操作元素了:
<!doctypehtml> <html> <head> <metacharset="utf-8"> <title>.ready()教程</title> </head> <body> <p>I'mthecontentofthiswebsite</p> <scriptsrc="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script> <script> varlength=$("p").length; //下面会在console控制台中输出1,表示有段落p存在. console.log(length); </script> </body> </html>
使用原生JavaScript替换ready()
对于现代浏览器,以及IE9+,你可以监听DOMContentLoaded事件:
document.addEventListener("DOMContentLoaded",function(){ //在DOM完全加载完后执行 });
在这里要记住当事件已经触发后回调方法不会执行(页面触发事件后才添加的这个事件监听).为了确保回调函数始终能执行,jQuery检测了document的readyState属性(参考),如果检测出的属性值是complete就立即执行回调函数:
varcallback=function(){ //在DOM完全加载完后执行 }; if( document.readyState==="complete"|| (document.readyState!=="loading"&&!document.documentElement.doScroll) ){ callback(); }else{ document.addEventListener("DOMContentLoaded",callback); }
你应该始终记得引入domReady库,它已经实现了这个解决方案.
老版本的IE
对于IE8及以下版本,你可以使用onreadystatechange事件来检测document的readyState属性:
document.attachEvent("onreadystatechange",function(){ //检测DOM是否加载完全 if(document.readyState==="complete"){ //为了确保在之后不会再触发移除事件监听 document.detachEvent("onreadystatechange",arguments.callee); //实际处理程序... } });
另外你可以使用load事件,像jQuery那样,这样就可以在所有的浏览器中正确的执行了.这也导致有一定的时间延迟,因为它会等所有的资源都加载完成.记住在这个解决方案中你还是得去检测readyState,如上所述,这是为了确保当事件已经触发后也能执行回调函数.
结论
如果你正在寻找一个原生JavaScript来代替ready方法你可以通过DOMContentLoaded事件来解决.如果你的系统需要支持IE那么你就要确保DOM已经加载完全!