jQuery 的 ready()的纯js替代方法


Posted in Javascript onNovember 20, 2016

ready 方法是 jQuery 实现的在 html 页面在 DOM(Document Object Model, 文档对象模型) 树完全加载完成后触发的一个方法. 因为它接收的方法在页面中所有的 DOM 都可访问时才执行, 所以此时你完全可以访问和操作 html 中的元素.

在 jQuery 3.0 之前, 典型的匿名函数方式的用法如下:

$(document).ready(function() {
 // 在 .ready() 被触发时执行.
});

在 jQuery 3.0 中 ready() 的变化

在 jQuery 3.0 发布之前, 有以下几种 ready 方法的使用方式:

在 document 对象上: $(document).ready(handler);

在一个空元素上: $().ready(handler);

或直接使用 (即: 不在一个指定的元素上): $(handler);

以上的几种方式是等价的. 传入的 handler 会在页面所有的 DOM 都加载完成后执行, 不管它被哪个指定元素执行. 也就是, 在 image 元素 $("img") 与 document 对象上调用 ready 方法不表明要等待这些元素加载完成后就触发 handler, 而是在整个 DOM 树加载完成后才触发.

在 jQuery 3.0 中, 除了 $(handler); 方法其它的都被弃用了. 官方的理由是:

因为这个选择与 .ready() 方法的行为没有关系, 它是低效的并且会误导用户猜测这个方法的行为.

Ready 和 Load 事件的不同点

ready 事件在页面 DOM 完全加载后触发并能正确的访问到元素. 而 load 事件在页面 DOM 及资源文件(图片,视频等)都加载完成后才触发.

load 事件可以像下面这样使用:

$(window).on("load", function(){
 // 当页面所有资源(图片,视频等)全加载完成后才加载执行
});

这会等待 DOM 加载完成以及图片加载完成(根据图片的大小, 需要加载一定的时间).

对于常规的 DOM 操作你多半不需要 load 事件, 但如果你想做一个等待页面所有资源加载的一个加载效果或者是计算图片的大小时这应该是一个不错的选择.

你可能并不需要 jQuery.ready()

ready 方法确保了其内部的代码都能正确的操作 DOM 元素. 这是什么意思? 当你把 JavaScript 代码放到 HTML 文档中时它会确保回调函数里面的代码在浏览器在已经加载页面中所有的元素时执行:

<!doctype html>
<html>
 <head>
  <meta charset="utf-8">
  <title>.ready() 教程</title>
  <script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
  <script>
   $(function(){ // .ready() 的回调方法, 在 DOM 完全加载完后执行
    var length = $("p").length;
    // 下面会在console控制台中输出 1, 表示有段落 p 存在.
    // 这就证明了这个回调方法在 DOM 完全加载完后执行.
    console.log(length);
   });
  </script>
 </head>
 <body>
  <p>I'm the content of this website</p>
 </body>
</html>

如果你把要执行的 JavaScript 放到 body 元素里面的最后位置, 你就不需要用 ready() 方法把代码包裹在里面了, 因为在 JavaScript 代码执行时页面中所有的元素都已经加载完成, 所以此时你就可以访问或操作元素了:

<!doctype html>
<html>
 <head>
  <meta charset="utf-8">
  <title>.ready() 教程</title>
 </head>
 <body>
  <p>I'm the content of this website</p>
  <script src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
  <script>
   var length = $("p").length;
   // 下面会在console控制台中输出 1, 表示有段落 p 存在.
   console.log(length);
  </script>
 </body>
</html>

使用原生 JavaScript 替换 ready()
对于现代浏览器, 以及 IE9+, 你可以监听 DOMContentLoaded 事件:

document.addEventListener("DOMContentLoaded", function(){
 // 在 DOM 完全加载完后执行
});

在这里要记住当事件已经触发后回调方法不会执行(页面触发事件后才添加的这个事件监听). 为了确保回调函数始终能执行, jQuery 检测了document 的 readyState 属性(参考), 如果检测出的属性值是 complete 就立即执行回调函数:

var callback = 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 已经加载完全!

Javascript 相关文章推荐
JQuery 无废话系列教程(一) jquery入门 [推荐]
Jun 23 Javascript
关于Aptana Studio生成自动备份文件的解决办法
Dec 23 Javascript
基于jQuery的history历史记录插件
Dec 11 Javascript
Jquery中Ajax 缓存带来的影响的解决方法
May 19 Javascript
alert中断settimeout计时功能
Jul 26 Javascript
jQuery Ajax异步处理Json数据详解
Nov 05 Javascript
Javascript学习笔记之 对象篇(四) : for in 循环
Jun 24 Javascript
搭建pomelo 开发环境
Jun 24 Javascript
js限制input标签中只能输入中文
Jun 26 Javascript
jquery遍历table的tr获取td的值实现方法
May 19 Javascript
Angular.JS中指令ng-if、ng-show/ng-hide和ng-switch的使用教程
May 07 Javascript
CocosCreator入门教程之网络通信
Apr 16 Javascript
node+experss实现爬取电影天堂爬虫
Nov 20 #Javascript
JSP防止网页刷新重复提交数据的几种方法
Nov 19 #Javascript
bootstrap datetimepicker2.3.11时间插件使用
Nov 19 #Javascript
js 定位到某个锚点的方法
Nov 19 #Javascript
js 模仿锚点定位的实现方法
Nov 19 #Javascript
Javascript使用function创建类的两种方法(推荐)
Nov 19 #Javascript
js 中获取制定的cook信息实现方法
Nov 19 #Javascript
You might like
php实现在线生成条形码示例分享(条形码生成器)
2013/12/30 PHP
PHP学习笔记(一) 简单了解PHP
2014/08/04 PHP
PHP+Ajax 检测网络是否正常实例详解
2016/12/16 PHP
Laravel使用支付宝进行支付的示例代码
2017/08/16 PHP
prototype Element学习笔记(Element篇三)
2008/10/26 Javascript
JS注册/移除事件处理程序(ExtJS应用程序设计实战)
2013/05/07 Javascript
Enter回车切换输入焦点实现思路与代码兼容各大浏览器
2014/09/01 Javascript
JavaScript中实现依赖注入的思路分享
2015/01/15 Javascript
使用Javascript写的2048小游戏
2015/11/25 Javascript
jQuery插件Easyui设置datagrid的pageNumber导致两次请求问题的解决方法
2016/08/06 Javascript
AngularJs ng-repeat 嵌套如何获取外层$index
2016/09/21 Javascript
Angular 2应用的8个主要构造块有哪些
2016/10/17 Javascript
JS绘制微信小程序画布时钟
2016/12/24 Javascript
tab栏切换原理
2017/03/22 Javascript
AngularJS实现表单验证功能详解
2017/10/12 Javascript
详解webpack中的hash、chunkhash、contenthash区别
2018/01/05 Javascript
vue router嵌套路由在history模式下刷新无法渲染页面问题的解决方法
2018/01/25 Javascript
基于vue-cli npm run build之后vendor.js文件过大的解决方法
2018/09/27 Javascript
Node.js中出现未捕获异常的处理方法
2020/06/29 Javascript
JavaScript中reduce()的5个基本用法示例
2020/07/19 Javascript
在Vue 中获取下拉框的文本及选项值操作
2020/08/13 Javascript
ES5和ES6中类的区别总结
2020/12/21 Javascript
Python定时执行之Timer用法示例
2015/05/27 Python
Python中逗号的三种作用实例分析
2015/06/08 Python
详解PyTorch批训练及优化器比较
2018/04/28 Python
PyCharm在新窗口打开项目的方法
2019/01/17 Python
python3实现钉钉消息推送的方法示例
2019/03/14 Python
ipython和python区别详解
2019/06/26 Python
Python函数的默认参数设计示例详解
2019/12/01 Python
python GUI库图形界面开发之PyQt5控件QTableWidget详细使用方法与属性
2020/02/25 Python
灵活运用CSS3特性绘制简易版围棋效果
2016/09/28 HTML / CSS
分享一个H5原生form表单的checkbox特效代码
2018/02/26 HTML / CSS
整理HTML5的一些新特性与Canvas的常用属性
2016/01/29 HTML / CSS
金属材料工程个人求职的自我评价
2013/12/04 职场文书
座谈会主持词
2014/03/20 职场文书
学校实习推荐信
2015/03/27 职场文书