//by Diego Perini 2007.10.5 function IEContentLoaded (w, fn) { var d = w.document, done = false, // 只执行一次用户的回调函数init() init = function () { if (!done) { done = true; fn(); } }; (function () { try { // DOM树未创建完之前调用doScroll会抛出错误 d.documentElement.doScroll('left'); } catch (e) { //延迟再试一次~ setTimeout(arguments.callee, 50); return; } // 没有错误就表示DOM树创建完毕,然后立马执行用户回调 init(); })(); //监听document的加载状态 d.onreadystatechange = function() { // 如果用户是在domReady之后绑定的函数,就立马执行 if (d.readyState == 'complete') { d.onreadystatechange = null; init(); } }; }
此外,IE还可以通过script defer hack进行判定
document.write("<script id=__ie_onload defer src=https://www.jb51.net//0 mce_src=http://0></scr"+"ipt>"); script = document.getElementById("__ie_onload"); script.onreadystatechange = function() { //IE即使是死链也能触发事件 if (this.readyState == "complete") init(); // 指定了defer的script在dom树建完才触发 };
不过还有个问题,如果我们的种子模块是动态加载的,在它插入dom树时,DOM树是否已经建完呢?这该怎么触发ready回调?jQuery的方案是,连onload也监听了 ,但如果连onload也没赶上,就判定document.readyState等于complete。(完美)可惜ff3.6之前没有这属性,看mass的方案
var readyList = []; mess.ready = function( fn ) { if ( readyList ) { fn.push( fn ); } else { fn(); } } var readyFn ,ready = W3C ? "DOMContentLoaded" : "readyStatechange"; function fireReady() { for (var i = 0 , fn; fn = readyList[i++]) { fn(); } readyList = null; fireReady = $.noop; //惰性函数,防止IE9调用_checkDeps } function doScrollCheck() { try { //IE下通过doScrollCheck检测DOM树是否建设完 html.doScroll("left"); fireReady(); } catch (e){ setTimeout(doScrollCheck); } } //FF3.6前,没有readyState属性 if (!document.readyState){ var readyState = document.readyState = document.body ? "complete" : "loading"; if (document.readyState === "complete") { fireReady(); //如果在domReay之外加载 } else { $.bind(document,ready,readyFn = function(){ if(W3C || document.readyState === "complete") { fireReady(); if(readyState){ //IE下不能该项document.readyState document.readyState = "complete"; } } }); if (html.doScroll){ try {//如果跨域就报错,证明有两个窗口 if (self.eval === parent.eval) { doScrollCheck(); } } catch (e) { doScrollCheck(); } } } }
6.无冲突处理
无冲突处理也叫多库共存,$是这个重要的函数名,以至于大家都爱拿它来做自己的命名空间,当jQuery开始发展时,Prototype是主流,jQuery发明了noConflict函数
var window = this, undefined, _jQuery = window.jQuery, _$ = window.$, //将window存入闭包中的同名变量,方便内部函数调用windows不用太麻烦查找它。 //_jQuery与_$用于以后重写 jQuery = window.jQuery = window.$ = function(selector, context){ //用于返回一个jQuery对象 return new jQuery.fn.init(selector,context); } jQuery.extend({ noConflict : function(deep) { //引入jQuery类库后,闭包外边的window.$与window.jQuery都储存着一个函数 //它是用来生成jQuery对象或在domReady后执行里面的函数 //回顾最上面的代码,在还没有把function赋值给它们时,_jQuery和_$已经被赋值了,因此,它们两的值必然是undefined //因此,这种放弃控制权的技术很简单,就是用undefined把window.$里边jQuery函数清除掉。 //这时,prototype或mootools的$就被拿走了 window.$ = _$; //相当于window.$ = undefined,如果你有一个叫jQuery的库,也能大方的过渡出去。 //这时,需要给noConflict添加一个布尔值,true if (deep) //但我们必须使用一个东西接纳jQuery与jQuey的入口函数 //闭包里边的东西除非被window等宿主引用,否则是不可见的 //因此,我们把闭包里的jQuery return出去,外面用一个变量接纳就可以 window.jQuery = _jQuery; //相当window.jQuery = undefined return jQuery; } })
使用时,先引入别人的库,然后引入jQuery,使用调用$.noConflict()进行改名,这样就不影响别人的$运行了。
mass的操作方式是在script标签上定义一个nick属性,那么释放出来的命名空间就是你的那个属性值。里面实现了类似jQuery的机制。
<script nike="aaa" src="https://www.jb51.net/mass.js"></script> <script> aaa.log("xxxxxx") </script>
以上所述就是本文的全部内容了,希望大家能够喜欢。
您可能感兴趣的文章: