模拟jQuery中的ready方法及实现按需加载css,js实例代码 - Web前端
作者:98wpeu发布时间:2026-06-18分类:网页前端技术浏览:5
导读:一、ready函数的实现经常用JQuery类库或其他类库中的ready方法,有时候想想它们到底是怎么实现的,但是看了一下jQuery中的源码,涉及到的模块比较多,(水平有限)代码比...
一、ready函数的实现
经常用JQuery类库或其他类库中的ready方法,有时候想想它们到底是怎么实现的,但是看了一下jQuery中的源码,涉及到的模块比较多,(水平有限)代码比较难看懂;自己结合了一些书籍内容,总结一下。
先说一下ready函数的实现思路:
变量ready通过表达式赋值,右侧为一个自执行匿名函数,在这个匿名函数中,首先为各个浏览器的事件绑定处理函数,并为isReady赋值(根据事件异步处理程序来确定),然后返回一个传参闭包,在闭包中,主要判断isReady值来执行操作,如果DOM结构准备就绪(isReady === true),执行回调,否则将回调加入到要执行的队列(funs)中,待事件处理程序执行时,循环遍历队列(funs),并依次执行队列中的函数,执行完队列中的函数后,还需要清除队列(funs = null)。
复制代码 代码如下:
var ready = (function(){
var isReady = false,
funs = [];
function handle (e) {
if ( isReady ) {
return;
}
if ( e.type === 'readystatechange' && (document.readyState !== 'interactive' && document.readyState !== 'complete') ) {
return;
}
for ( var i = 0; i < funs.length; i++ ) {
funs[i].call(document);
}
isReady = true;
funs = Null;
}
if ( document.addEventListener ) {
document.addeventlistener( 'domContentloaded', handle, false );
document.addEventListener( 'readystatechange', handle, false );
document.addEventListener( 'load', handle, false );
}
else if ( document.attachEvent ) {
document.attachEvent( 'onreadystatechange', handle );
document.attachEvent( 'onload', handle );
}
return function ready (callback) {
if ( isReady ) {
callback.call(document);
}
else {
funs.push(callback);
}
};
}());
PS:
该函数代码参照于权威指南书籍,唯一不同的是,多加了一个判断document.readyState !== 'interactive'
复制代码 代码如下:
if ( e.type === 'readystatechange' && (document.readyState !== 'interactive' && document.readyState !== 'complete') ) {
return;
}
在各个浏览器中交互和完成状态出现顺序并不能保证一致,这取决于浏览器及页面的内容,多加了这个判断document.readyState !== 'interactive'的话,
意思是不管哪个阶段先出现,代码都能更早的执行。
二、按需加载CSS,JS
参照了jquery源码,写了一个type函数,返回参数类型。
复制代码 代码如下:
/**
*
* 判断参数类型
* createtime: 2013/9/18
*
*/
function type (obj) {
var classTypes, ObjectTypes;
if ( obj == null ) {
return string(obj);
}
classTypes = {};
objectTypes = ('Boolean Number String Function ArraydateRegExp Object error').split(' ');
for ( var i = 0, len = objectTypes.length; i < len; i++ ) {
classTypes[ '[object ' + objectTypes[i] + ']' ] = objectTypes[i].toLowerCase();
}
if ( typeof obj === 'object' || typeof obj === 'function' ) {
var key = Object.prototype.toString.call(obj);
return classTypes[key];
}
return typeof obj;
}
复制代码 代码如下:
// css按需加载
function loadCss (cssurl, callback) {
var elem, bl,
isExecuted = false; // 防止在ie9中,callback执行两次
if ( cssUrl == null ) {
return String(cssUrl);
}
elem = document.createElement('link'),
elem.rel = 'StyleSheet';
if ( type(callback) === 'function' ) {
bl = true;
}
// for ie
function handle() {
if ( elem.readyState === 'loaded' || elem.readyState === 'complete' ) {
if (bl && !isExecuted) {
callback();
isExecuted = true;
}
elem.onreadystatechange = null;
}
}
elem.onreadystatechange = handle;
// for 非IE
if (bl && !isExecuted) {
elem.onload = callback;
isExecuted = true;
}
elem.href = cssUrl;
document.getElementsByTagName('head')[0].appendChild(elem);
}
// js按需加载
function loadScript(scriptUrl, callback) {
var elem, bl,
isExecuted = false; // 防止在ie9中,callback执行两次
if (scriptUrl == null) {
return String(fn);
}
elem = document.createElement('script');
if ( type(callback) === 'function' ) {
bl = true;
}
// for ie
function handle(){
var status = elem.readyState;
if (status === 'loaded' || status === 'complete') {
if (bl && !isExecuted) {
callback();
isExecuted = true;
}
elem.onreadystatechange = null;
}
}
elem.onreadystatechange = handle;
// for 非ie
if (bl && !isExecuted) {
elem.onload = callback;
isExecuted = true;
}
elem.src = scriptUrl;
document.getElementsByTagName('head')[0].appendChild(elem);
}
PS: 在判断link,script元素是否加载完毕,主要依靠load事件;而在ie9以下浏览器中,并没有load事件,ie为它们都添加了一个readystatechange事件,通过判断
元素的readyState状态确定元素是否已经加载完毕;而奇怪的是,在ie9(还可能存在其他浏览器版本)中,元素既有load事件又有readystatechange事件,因此在代码中添加了一个变量isExecuted,如果执行过回调,那么就不再执行,避免回调执行两次。
三、调用方式
复制代码 代码如下:
loadCss('http://www.jb51.net/APPs/tBTx/miiee/css/base.css', function(){
console.log('css加载完毕');
});
loadScript('HTTP://www.jb51.net/apps/tbtx/miiee/js/jquery.js', function(){
console.log('js加载完毕');
});
ready(function(){
console.log('dom is ready!');
});
经常用JQuery类库或其他类库中的ready方法,有时候想想它们到底是怎么实现的,但是看了一下jQuery中的源码,涉及到的模块比较多,(水平有限)代码比较难看懂;自己结合了一些书籍内容,总结一下。
先说一下ready函数的实现思路:
变量ready通过表达式赋值,右侧为一个自执行匿名函数,在这个匿名函数中,首先为各个浏览器的事件绑定处理函数,并为isReady赋值(根据事件异步处理程序来确定),然后返回一个传参闭包,在闭包中,主要判断isReady值来执行操作,如果DOM结构准备就绪(isReady === true),执行回调,否则将回调加入到要执行的队列(funs)中,待事件处理程序执行时,循环遍历队列(funs),并依次执行队列中的函数,执行完队列中的函数后,还需要清除队列(funs = null)。
复制代码 代码如下:
var ready = (function(){
var isReady = false,
funs = [];
function handle (e) {
if ( isReady ) {
return;
}
if ( e.type === 'readystatechange' && (document.readyState !== 'interactive' && document.readyState !== 'complete') ) {
return;
}
for ( var i = 0; i < funs.length; i++ ) {
funs[i].call(document);
}
isReady = true;
funs = Null;
}
if ( document.addEventListener ) {
document.addeventlistener( 'domContentloaded', handle, false );
document.addEventListener( 'readystatechange', handle, false );
document.addEventListener( 'load', handle, false );
}
else if ( document.attachEvent ) {
document.attachEvent( 'onreadystatechange', handle );
document.attachEvent( 'onload', handle );
}
return function ready (callback) {
if ( isReady ) {
callback.call(document);
}
else {
funs.push(callback);
}
};
}());
PS:
该函数代码参照于权威指南书籍,唯一不同的是,多加了一个判断document.readyState !== 'interactive'
复制代码 代码如下:
if ( e.type === 'readystatechange' && (document.readyState !== 'interactive' && document.readyState !== 'complete') ) {
return;
}
在各个浏览器中交互和完成状态出现顺序并不能保证一致,这取决于浏览器及页面的内容,多加了这个判断document.readyState !== 'interactive'的话,
意思是不管哪个阶段先出现,代码都能更早的执行。
二、按需加载CSS,JS
参照了jquery源码,写了一个type函数,返回参数类型。
复制代码 代码如下:
/**
*
* 判断参数类型
* createtime: 2013/9/18
*
*/
function type (obj) {
var classTypes, ObjectTypes;
if ( obj == null ) {
return string(obj);
}
classTypes = {};
objectTypes = ('Boolean Number String Function ArraydateRegExp Object error').split(' ');
for ( var i = 0, len = objectTypes.length; i < len; i++ ) {
classTypes[ '[object ' + objectTypes[i] + ']' ] = objectTypes[i].toLowerCase();
}
if ( typeof obj === 'object' || typeof obj === 'function' ) {
var key = Object.prototype.toString.call(obj);
return classTypes[key];
}
return typeof obj;
}
复制代码 代码如下:
// css按需加载
function loadCss (cssurl, callback) {
var elem, bl,
isExecuted = false; // 防止在ie9中,callback执行两次
if ( cssUrl == null ) {
return String(cssUrl);
}
elem = document.createElement('link'),
elem.rel = 'StyleSheet';
if ( type(callback) === 'function' ) {
bl = true;
}
// for ie
function handle() {
if ( elem.readyState === 'loaded' || elem.readyState === 'complete' ) {
if (bl && !isExecuted) {
callback();
isExecuted = true;
}
elem.onreadystatechange = null;
}
}
elem.onreadystatechange = handle;
// for 非IE
if (bl && !isExecuted) {
elem.onload = callback;
isExecuted = true;
}
elem.href = cssUrl;
document.getElementsByTagName('head')[0].appendChild(elem);
}
// js按需加载
function loadScript(scriptUrl, callback) {
var elem, bl,
isExecuted = false; // 防止在ie9中,callback执行两次
if (scriptUrl == null) {
return String(fn);
}
elem = document.createElement('script');
if ( type(callback) === 'function' ) {
bl = true;
}
// for ie
function handle(){
var status = elem.readyState;
if (status === 'loaded' || status === 'complete') {
if (bl && !isExecuted) {
callback();
isExecuted = true;
}
elem.onreadystatechange = null;
}
}
elem.onreadystatechange = handle;
// for 非ie
if (bl && !isExecuted) {
elem.onload = callback;
isExecuted = true;
}
elem.src = scriptUrl;
document.getElementsByTagName('head')[0].appendChild(elem);
}
PS: 在判断link,script元素是否加载完毕,主要依靠load事件;而在ie9以下浏览器中,并没有load事件,ie为它们都添加了一个readystatechange事件,通过判断
元素的readyState状态确定元素是否已经加载完毕;而奇怪的是,在ie9(还可能存在其他浏览器版本)中,元素既有load事件又有readystatechange事件,因此在代码中添加了一个变量isExecuted,如果执行过回调,那么就不再执行,避免回调执行两次。
三、调用方式
复制代码 代码如下:
loadCss('http://www.jb51.net/APPs/tBTx/miiee/css/base.css', function(){
console.log('css加载完毕');
});
loadScript('HTTP://www.jb51.net/apps/tbtx/miiee/js/jquery.js', function(){
console.log('js加载完毕');
});
ready(function(){
console.log('dom is ready!');
});
相关推荐
- 用jquery写的一个万年历(自写) - Web前端
- jquery提交form表单时禁止重复提交的方法 - Web前端
- jquery操作select详解(取值,设置选中) - Web前端
- jquery 字符串切割函数substring的用法说明 - Web前端
- Jquery Uploadify上传带进度条的简单实例 - Web前端
- 文本框文本自动补全效果示例分享 - Web前端
- jQuery插件开发的两种方法及$.fn.extend的详解 - Web前端
- 为指定的元素添加遮罩层的示例代码 - Web前端
- jquery事件重复绑定的快速解决方法 - Web前端
- Jquery 获取对象的几种方式介绍 - Web前端
- 网页前端技术排行
-
- 1【第六章】Foundation之按钮和下拉功能 - Web前端
- 2在Mac/PC上远程调试iPhone/iPad上的网页 - Web前端
- 3jQuery编写widget的一些技巧分享 - Web前端
- 4基于jquery的滚动条滚动固定div(附演示下载) - Web前端
- 5jQuery实例教程:制作网页中可折叠的面板 - Web前端
- 6分析Iconfont-阿里巴巴矢量常用图标库 - Web前端
- 7JS网页制作实例:标签云 - Web前端
- 8[Web前端]用javascript实现默认图片替代未显示的图片 - Web前端
- 9分享精心挑选的12款优秀jQuery Ajax分页插件和教程 - Web前端
- 最近发表
-
- WordPress随机显示特色图片插件:Random Post Thumbnails
- KeePass实现Chrome浏览器自动填充密码方法一
- LNMP一键包nginx 301强制跳转到https教程
- KeePass实现Chrome浏览器自动填充密码方法二
- #建站# 免费的VPS管理软件Xshell8/Xftp8中文版下载
- 使用Xshell 8连接VPS教程_电脑登录vps的方法
- WordPress评论界面添加烟花????效果
- 不同浏览器书签同步方案:坚果云+Floccus_详细使用教程
- iOS端KeePassXC客户端APP:Strongbox Password Safe
- 给WordPress评论中的Gravatar头像图片添加ALT属性


