今天来总结下在项目中事件使用的以下问题
*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;
*事件注意点
绑定事件的时候一定要搞清楚事件的对象,事件句柄,事件的触发条件
欢迎大家拍砖。。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述