【jQuery源码浅析】(五)--文档加载--$.ready
来源:互联网 发布:挚爱梵高 知乎 编辑:程序博客网 时间:2024/05/22 00:45
前言
我们经常会用到$(document).ready(fn)或者$(fn),可是,我们只是用这个函数来代替window.onload么?其实不是的,文档的加载除了DOM结构树的加载之外还包括其他外部资源如图片或脚本的加载,而所有资源的加载会触发window.onload函数,但我们不可能总等所有资源加载出来再执行接下来的代码,有时候加载的外部资源很大的时候,我们就可以先在DOM结构树加载完之后开始做事了,不用等其他资源加载完毕。
我们可以通过反复监听DOMContentLoaded的方式来实现类似ready的功能。但是$(document).ready(fn)实现的方式不是通过直接监听DOMContentLoaded达到目的的。
大多数浏览器提供了 DOMContentLoaded 事件形式的类似功能。 然而,jQuery的 .ready() 方法的不同之处在于它是一个重要并且有效的方法:在代码调用.ready( handler )之前,如果 DOM 已经准备就绪并且浏览器已经触发DOMContentLoaded,handler处理函数仍然会被执行。 相反,如果 DOMContentLoaded 事件侦听器在这个事件触发后才被添加进来,那么这个DOMContentLoaded 事件的处理程序将永远不会被执行。
有的人会问为什么一定要传个document进去,然而,这不是必然的,也可以写成$().ready(fn)
或者人们常用的$(fn)
,document不是必然的,因为高版本的jQuery已经把document传进去了rootjQuery = jQuery( document )
,更推荐写法$( handler )的简洁方式。
在jQuery 3.0 中,只建议使用第一种语法(愚人码头注:即 $( handler )); 其他语法仍然能正常工作,但已被标记为弃用(愚人码头注:将来的某个版本会被删除)。
核心源码
var readyList = jQuery.Deferred();3865 jQuery.fn.ready = function( fn ) { readyList .then( fn ) // Wrap jQuery.readyException in a function so that the lookup // happens at the time of error handling instead of callback // registration. .catch( function( error ) { jQuery.readyException( error ); } ); return this; };
思路分析
- 基本思想:实现文档加载完毕而不是所有资源加载完毕后立刻执行的函数。
- 简便写法:实现$(fn) === $().ready(fn) === $(document).ready(fn),由于跟传入的selector无关,只跟selector是否为function有关,因此应该使用简便写法。
源码分析
1)首先$().ready(fn)
里面调用的应该是一个延迟对象Deferred或Promise,看源码可知是一个Deferred。
jQuery.Deferred() // jQuery.js加载时候就执行 .then( fn ) // 先执行完deferred里面的内容在执行fn .catch( function( error ) { // 如果fn出错则用jQuery默认的ready异常处理方式 jQuery.readyException( error ); } ) // jQuery使用的ready异常处理方式是保证DOM刷新完毕再把异常抛给window jQuery.readyException = function( error ) { window.setTimeout( function() { throw error; } ); };
readyException表面上看是多此一举,可这恰恰可以避免异常。
发现没有?ready里面与selector根本没有任何关系,所以不再推荐传入document了。
2)为什么创造一个Deferred出来就可以保证DOM肯定是完全加载的呢?原因是Deferred内部的then方法做了一个setTimeOut的操作,而已做了递归。所以保证了DOM肯定是完全加载,相当于监听了DOMContentLoaded
process = special ? mightThrow : function() { .... if ( depth ) { // 递归 process(); } else { .... window.setTimeout( process ); // 等待DOMContentLoaded完成 } }
所以调用$().ready()结果如下:
3)调用$(fn)就等于调用$().ready()
root = rootjQuery = jQuery( document ); // 默认把document传进去了 // selector是方法的话,就是我们平时写的$(fn) else if ( jQuery.isFunction( selector ) ) { return root.ready !== undefined ? root.ready( selector ) : //ready还存在的时候就调用ready // Execute immediately if ready is not present selector( jQuery ); // ready不存在的时候就直接调用该方法(不需要等待),这就是我们常用的$(function($)) }
最后总结
由jQuery的版本迭代情况来看,window.onload会逐渐被淘汰,随着网页的体积越来越大和外部资源越来越多,为了用户体验,这个方法基本上是不会使用的了。另外,DOMContentLoaded会逐渐被setTimeout取代。jQuery.Deferred的作用也会越来越强大,关于Deferred的介绍将会在后续文章中进行阐述。
相关资料
- setTimeOut()定时器强大作用
- .ready( handler ) 中文API
- jQuery3.1.1.js源码下载
- 【jQuery源码浅析】(五)--文档加载--$.ready
- JQuery 加载就绪(ready)
- jQuery源码解析(3)—— ready加载、queue队列
- jQuery源码学习(版本1.11)-ready
- 你真的了解jQuery的ready函数吗?当 DOM(文档对象模型) 已经加载,就执行ready里的代码。DOM何时加载完毕?jQuery对html局部操作,DOM为什么不重新加载?
- jQuery入门:ready加载问题
- jquery源码解析----DOM文档加载步骤
- jQuery源码之ready()事件
- jQuery中的ready和load事件(源码解析)
- jQuery源码阅读(九)---ready函数理解
- jquery的加载函数ready的用法
- 【jQuery】页面加载时触发ready()事件
- 【JQuery】页面加载时触发ready()事件
- Jquery的Ready方法加载为什么两次?
- jQuery源码阅读[2]document ready
- jQuery源码分析之ready方法
- jQuery页面加载时触发ready()事件 dom结构加载完成就触发。(参考慕课网)
- 【jQuery源码浅析】(一)--整体架构
- 写给小白看的Retrofit使用指南
- KVO键值观察运用及其原理
- 在ssh项目中spring在action注入service为null
- ActiveList API
- 安卓目录地址getCacheDir()、getFilesDir()、getExternalFilesDir()、getExternalCacheDir()的作用
- 【jQuery源码浅析】(五)--文档加载--$.ready
- iOS的runtime获取类的属性的数据类型
- 翻滚的TextView
- myeclipse打开软件出现Building workspace’has encountered a problem.Error occurred during the build。错误
- 007_内核对象的Signal状态
- Activity的总结(一)
- 供SAPI中TTS功能用使的Win8.1语言包安装
- TokenSearchManager API
- 让APK只包含指定的ABI