跨浏览器事件的其他问题(小记)

今天来总结下在项目中事件使用的以下问题 

*DOMContentLoaded在不同浏览器的实现

  什么是DOMContentLoaded? 它是firefox为了处理在页面DOM结构建立后(无需下载js,css,img等图片资源)绑定事件的一个方法,对于IE是没有这个方法的,但是在IE中可以模拟出这个方法来,来达到同样的目的。我们经常使用jquery的 $(document).ready(function(){});或者百度的tangram框架的时候, baidu.dom.ready(function(){})其实是对这个方法在不同浏览器中做了一个封装。

在IE中的实现方式,我们可以参考这个文档http://javascript.nwbox.com/IEContentLoaded/ ,他的原理是:在IE下,DOM的某些方法只有在DOM解析完成后才可以调用,doScroll就是这样一个方法,当然反过来当能调用doScroll的时候即是DOM解析完成之时。下面我们来看看jquery和tangram的实现方式,来加深理解

1)jquery

 bindReady: function() {

if ( readyList ) {
return;
}
readyList = jQuery.Callbacks( "once memory" );
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
return setTimeout( jQuery.ready, 1 );
}
 
// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
// 给加载在document上去。
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
 
// 确保事件真正的执行
window.addEventListener( "load", jQuery.ready, false );
 
// 如果是IE的事件模式
} else if ( document.attachEvent ) {
// ensure firing before onload,
// 如果是是iframe的形式的话
document.attachEvent( "onreadystatechange", DOMContentLoaded );
 
// 确保这个函数被真正的使用了
window.attachEvent( "onload", jQuery.ready );
 
// 如果是IE序列的浏览器,并且不是在iframe使用
// continually check to see if the document is ready
var toplevel = false;
 
try {
toplevel = window.frameElement == null;
} catch(e) {}
         //如果支持doScroll 并且不是在iframe的时候
if ( document.documentElement.doScroll && toplevel ) {
doScrollCheck();
}
}
}

 // 在IE序列浏览器下,检测 DOM ready  

function doScrollCheck() {
if ( jQuery.isReady ) {
return;
}
 
try {

document.documentElement.doScroll("left");
} catch(e) {
setTimeout( doScrollCheck, 1 );
return;
}
 
//执行该要执行的函数
jQuery.ready();
}

在代码中我都解释了。

2)tangram:

 

(function() {
 
    var ready = baidu.dom.ready = function() {
        var readyBound = false,
            readyList = [],
            DOMContentLoaded;
 
        if (document.addEventListener) {
            DOMContentLoaded = function() {
                document.removeEventListener('DOMContentLoaded', DOMContentLoaded, false);
                ready();
            };
 
        } else if (document.attachEvent) {
            DOMContentLoaded = function() {
                if (document.readyState === 'complete') {
                    document.detachEvent('onreadystatechange', DOMContentLoaded);
                    ready();
                }
            };
        }
 
        function ready() {
            if (!ready.isReady) {
                ready.isReady = true;
                for (var i = 0, j = readyList.length; i < j; i++) {
                    readyList[i]();
                }
            }
        }
 
        function doScrollCheck(){
            try {
                document.documentElement.doScroll("left");
            } catch(e) {
                setTimeout( doScrollCheck, 1 );
                return;
            }   
            ready();
        }
 
        function bindReady() {
            if (readyBound) {
                return;
            }
            readyBound = true;
 
            if (document.addEventListener) {
 
                document.addEventListener('DOMContentLoaded', DOMContentLoaded, false);
                window.addEventListener('load', ready, false);
 
            } else if (document.attachEvent) {
 
                document.attachEvent('onreadystatechange', DOMContentLoaded);
                window.attachEvent('onload', ready);
 
                var toplevel = false;
 
                try {
                    toplevel = window.frameElement == null;
                } catch (e) {}
 
                if (document.documentElement.doScroll && toplevel) {
                    doScrollCheck();
                }
            }
        }
        bindReady();
 
        return function(callback) {
            ready.isReady ? callback() : (readyList[readyList.length] = callback);
        };
    }();
 
    ready.isReady = false;
})();
可以看出tangram的实现方式和jquery一样的。

 

*阻止事件默认行为

判断是否支持 preventDefault 函数,如果不支持的话,就将事件的属性returnValue 设置为false,常见的写法为
 if (event.preventDefault) {

       event.preventDefault();
 } else {
       event.returnValue = false;

*阻止事件传播

判断是否支持stopPropagation,如果不支持的话,就将事件的属性cancelBubble设置为true,常见的写法为 

   if (event.stopPropagation) {
       event.stopPropagation();
   } else {
       event.cancelBubble = true;

   } 

*获取对象

target = event.srcElement ||event.target

*获取鼠标事件的X,Y坐标

 x = event.pageX !== 0 ?event.pageX:event.clientX +document.body.scrollLeft||document.documentElement.scrollLeft;

   y = event.pageY !== 0 ?event.pageY:event.clientY +document.body.scrollTop||document.documentElement.scrollTop;

*获取键盘的键值

value = event.which || event.keyCode; 

*事件的其他属性

  事件的相关对象,处理从一个节点到其子节点中处理很方便的,标准浏览器是支持  relatedTarget ,在IE下是不一样的。

 var reltarget = e.relatedTarget ? e.relatedTarget : e.type == 'mouseout' ? e.toElement:e.fromElement;

*事件注意点 

   绑定事件的时候一定要搞清楚事件的对象,事件句柄,事件的触发条件

欢迎大家拍砖。。 

 

posted @ 2012-03-16 08:37  yupeng  阅读(1582)  评论(0编辑  收藏  举报