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 相关文章推荐
javascript的函数、创建对象、封装、属性和方法、继承
Mar 10 Javascript
jQuery插件实现表格隔行换色且感应鼠标高亮行变色
Sep 22 Javascript
jQuery操作CheckBox的方法介绍(选中,取消,取值)
Feb 04 Javascript
浅析Javascript中“==”与“===”的区别
Dec 23 Javascript
js限制input标签中只能输入中文
Jun 26 Javascript
jquery带有索引按钮且自动轮播切换特效代码分享
Sep 15 Javascript
vue.js 初体验之Chrome 插件开发实录
May 13 Javascript
聊聊Vue.js的template编译的问题
Oct 09 Javascript
小程序异步问题之多个网络请求依次执行并依次收集请求结果
May 05 Javascript
vue语法自动转typescript(解放双手)
Sep 18 Javascript
vue 导航锚点_点击平滑滚动,导航栏对应变化详解
Aug 10 Javascript
javascript中闭包closure的深入讲解
Mar 03 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
为什么夜间收到的中波电台比白天多
2021/03/01 无线电
PHP类继承 extends使用介绍
2014/01/14 PHP
php利用腾讯ip分享计划获取地理位置示例分享
2014/01/20 PHP
php集成环境xampp中apache无法启动问题解决方案
2014/11/18 PHP
PHP模拟asp中response类实现方法
2015/08/08 PHP
一键生成各种尺寸Icon的php脚本(实例)
2017/02/08 PHP
php实现的三个常用加密解密功能函数示例
2017/11/06 PHP
PHP封装mysqli基于面向对象的mysql数据库操作类与用法示例
2019/02/25 PHP
ThinkPHP5&amp;5.1实现验证码的生成、使用及点击刷新功能示例
2020/02/07 PHP
Laravel6.18.19如何优雅的切换发件账户
2020/06/14 PHP
JSON 教程 json入门学习笔记
2020/09/22 Javascript
Jquery 动态循环输出表格具体方法
2013/11/23 Javascript
Jquery uploadify图片上传插件无法上传的解决方法
2013/12/16 Javascript
在AngularJS应用中实现一些动画效果的代码
2015/06/18 Javascript
JS实现淡入淡出图片效果的方法分析
2016/12/20 Javascript
Vue.js:使用Vue-Router 2实现路由功能介绍
2017/02/22 Javascript
js中字符型和数值型数字的互相转化方法(必看)
2017/04/25 Javascript
JavaScript实现的数字与字符串转换功能示例
2017/08/23 Javascript
JS实现点击复选框变更DIV显示状态的示例代码
2017/12/18 Javascript
Vue路由history模式解决404问题的几种方法
2018/09/29 Javascript
关于Vue源码vm.$watch()内部原理详解
2019/04/26 Javascript
JavaScript中遍历的十种方法总结
2020/12/15 Javascript
[01:37]TI4西雅图DOTA2前线报道 VG拿下首胜教练357给出获胜秘诀
2014/07/10 DOTA
使用python实现省市三级菜单效果
2016/01/20 Python
Django contenttypes 框架详解(小结)
2018/08/13 Python
快速解决jupyter notebook启动需要密码的问题
2020/04/21 Python
详解Canvas 实现炫丽的粒子运动效果(粒子生成文字)
2018/02/01 HTML / CSS
ProBikeKit美国官网:自行车套件,跑步和铁人三项套件
2016/10/13 全球购物
全球烹饪课程的领先预订平台:Cookly
2020/01/28 全球购物
英文简历自荐信范文
2013/12/11 职场文书
老干部工作先进集体事迹材料
2014/05/21 职场文书
贫困生助学金感谢信
2015/01/21 职场文书
秦兵马俑导游词
2015/02/02 职场文书
2015年党员个人自我评价
2015/03/03 职场文书
新学期开学标语2015
2015/07/16 职场文书
python画条形图的具体代码
2022/04/20 Python