最近在写一个Javascript的框架,刚把DOMContentLoaded事件封装好,略带小兴奋,把开发过程中遇到的原理和兼容性问题做篇笔记,省的忘记到处找。
我们在写js代码的时候,一般都会添加window.onload事件,主要是为了在DOM加载完后可以使用getElementById,getElementsByTagName等方法选取DOM元素进行操作,但是window.load会等到加载完DOM、脚本、CSS,最后加载完图片甚至是iframe中的所有资源才会触发,很多时候网页的图片较多较大,要等最后图片这个耗时大户加载完才执行js明显有些太迟了,很多时候都会影响用户体验。
很多js框架都有个document.ready的功能,像JQuery的$(document).ready()方法,可以在DOM加载完就立即执行js代码,让图片自个慢慢加载吧。
document.ready的核心是DOMContentLoaded事件,firefox、chrome、opera、safari、ie9+都可以使用addEventListener(‘DOMContentLoaded',fn,false)进行事件绑定,而ie6~8不支持DOMContentLoaded事件,所以要针对ie6~8做兼容性处理。
资料上说ie6~8可以使用document.onreadystatechange事件监听document.readyState状态是否等于complete来判断DOM是否加载完毕,如果页面中嵌有iframe的话,ie6~8的document.readyState会等到iframe中的所有资源加载完才会变成complete,此时iframe变成了耗时大户。但是经过测试,即使页面中没有iframe,当readyState等于complete时,实际触发的是onload事件而不是DOMContentLoaded事件,对这点表示惊奇。
还好ie有个特有的doScroll方法,当页面DOM未加载完成时,调用doScroll方法时,就会报错,反过来,只要一直间隔调用doScroll直到不报错,那就表示页面DOM加载完毕了,不管图片和iframe中的内容是否加载完毕,此法都有效。
如果有多个js文件绑定了document.ready事件,为了防止浏览器重复绑定,同时有序执行,可以引入一个事件队列机制来解决。
以上就是document.ready事件的原理和兼容性问题,下面贴段实例代码,为了方便理解执行过程,使用函数封装的模式,执行过程都写在注释里了,如果有不妥之处欢迎指教。
//保存domReady的事件队列 eventQueue = []; //判断DOM是否加载完毕 isReady = false; //判断DOMReady是否绑定 isBind = false; /*执行domReady() * *@param {function} *@execute 将事件处理程序压入事件队列,并绑定DOMContentLoaded * 如果DOM加载已经完成,则立即执行 *@caller */ function domReady(fn){ if (isReady) { fn.call(window); } else{ eventQueue.push(fn); }; bindReady(); }; /*domReady事件绑定 * *@param null *@execute 现代浏览器通过addEvListener绑定DOMContentLoaded,包括ie9+ ie6-8通过判断doScroll判断DOM是否加载完毕 *@caller domReady() */ function bindReady(){ if (isReady) return; if (isBind) return; isBind = true; if (window.addEventListener) { document.addEventListener('DOMContentLoaded',execFn,false); } else if (window.attachEvent) { doScroll(); }; }; /*doScroll判断ie6-8的DOM是否加载完成 * *@param null *@execute doScroll判断DOM是否加载完成 *@caller bindReady() */ function doScroll(){ try{ document.documentElement.doScroll('left'); } catch(error){ return setTimeout(doScroll,20); }; execFn(); }; /*执行事件队列 * *@param null *@execute 循环执行队列中的事件处理程序 *@caller bindReady() */ function execFn(){ if (!isReady) { isReady = true; for (var i = 0; i < eventQueue.length; i++) { eventQueue[i].call(window); }; eventQueue = []; }; }; //js文件1 domReady(function(){ ... }); //js文件2 domReady(function(){ ... }); //注意,如果是异步加载的js就不要绑定domReady方法,不然函数不会执行, //因为html" target="_blank">异步加载的js下载之前,DOMContentLoaded已经触发,addEventListener执行时已经监听不到了
测试页面:都加载了两张很大的图片,onload需要图片加载完才能执行js,DOMContentLoaded只需等到DOM加载完即可执行js。可以打开firebug查看加载过程,每次测试前记得先清理下浏览器缓存。
本文向大家介绍javascript移动设备Web开发中对touch事件的封装实例,包括了javascript移动设备Web开发中对touch事件的封装实例的使用技巧和注意事项,需要的朋友参考一下 在触屏设备上,一些比较基础的手势都需要通过对 touch 事件进行二次封装才能实现。 zepto 是移动端上使用率比较高的一个类库,但是其 touch 模块模拟出来的一些事件存在一些兼容性问题,如 tap
本文向大家介绍自己封装的javascript事件队列函数版,包括了自己封装的javascript事件队列函数版的使用技巧和注意事项,需要的朋友参考一下 背景 javascript中使用addEventListener()或attachEvent()绑定事件时会有几个小问题: 一、使用addEventListener()或attachEvent()添加的匿名函数无法移除。 二、ie6-ie8中,使用
问题内容: 和事件有什么区别? 问题答案: 从Mozilla开发人员中心: 当文档已完全加载和解析时,将触发DOMContentLoaded事件,而无需等待样式表,图像和子帧完成加载(可以使用load事件来检测完全加载的页面)。
本文向大家介绍onload事件和domcontentloaded哪个先执行呢?相关面试题,主要包含被问及onload事件和domcontentloaded哪个先执行呢?时的应答技巧和注意事项,需要的朋友参考一下 window.onload:它表示页面上的元素全部都加载完成,包括(图片,样式表等资源),它是属于原声Js 中的一个方法, 他只能注册一个。 document.onDOMContentLo
本文向大家介绍基于jQuery拖拽事件的封装,包括了基于jQuery拖拽事件的封装的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了基于jQuery封装的拖拽事件,供大家参考,具体内容如下 HTML代码: 封装的jQuery拖拽事件: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
本文向大家介绍javascript 封装Date日期类实例详解,包括了javascript 封装Date日期类实例详解的使用技巧和注意事项,需要的朋友参考一下 javascript-封装Date日期类 (一)对日期进行格式化 自定义Date日期类的format()格式化方法 方式一:(非原创) 测试: (二)根据日期返回本周周一和周日的日期 测试: 注意: