最近在学习李炎恢老师的javascipt,下面是贴出边学边记录学习的代码笔记,方便以后可以查阅。
一.问题所在
现代绑定中 W3C 使用的是:addEventListener 和 removeEventListener。IE 使用的是
attachEvent 和 detachEvent。我们知道 IE 的这两个问题多多,并且伴随内存泄漏。所以,解
决这些问题非常有必要。
那么我们希望解决非 IE 浏览器事件绑定哪些问题呢?
1.支持同一元素的同一事件句柄可以绑定多个监听函数;
2.如果在同一元素的同一事件句柄上多次注册同一函数, 那么第一次注册后的所有注册
都被忽略;
3.函数体内的 this 指向的应当是正在处理事件的节点(如当前正在运行事件句柄的节
点) ;
4.监听函数的执行顺序应当是按照绑定的顺序执行;
5.在函数体内不用使用 event = event || window.event; 来标准化 Event 对象;
下面对事件封装的代码:
在tool.js文件中的代码:
/*
//实现累加,并且清晰的指出是专给addEvent用的
//JS一切皆为对象,所以addEvent.ID语法正确,实际上是个全局变量
alert(addEvent.ID);
addEvent.ID++;
*/
//跨浏览器添加事件绑定
function addEvent(obj, type, fn) {
if (typeof obj.addEventListener != 'undefined') {
obj.addEventListener(type, fn, false);
} else {
//创建一个存放事件的哈希表(散列表)
if (!obj.events) obj.events = {};
//第一次执行时执行
if (!obj.events[type]) {
//创建一个存放事件处理函数的数组
obj.events[type] = [];
//把第一次的事件处理函数先储存到第一个位置上
if (obj['on' + type]) obj.events[type][0] = fn;
} else {
//同一个注册函数进行屏蔽,不添加到计数器中
if (addEvent.equal(obj.events[type], fn)) return false;
}
//从第二次开始我们用事件计数器来存储
obj.events[type][addEvent.ID++] = fn;
//执行事件处理函数
obj['on' + type] = addEvent.exec;
}
}
//为每个事件分配一个计数器
addEvent.ID = 1;
//执行事件处理函数
addEvent.exec = function (event) {
var e = event || addEvent.fixEvent(window.event);
var es = this.events[e.type];
for (var i in es) {
es[i].call(this, e);
}
};
//同一个注册函数进行屏蔽
addEvent.equal = function (es, fn) {
for (var i in es) {
if (es[i] == fn) return true;
}
return false;
}
//把IE常用的Event对象配对到W3C中去
addEvent.fixEvent = function (event) {
event.preventDefault = addEvent.fixEvent.preventDefault;
event.stopPropagation = addEvent.fixEvent.stopPropagation;
return event;
};
//IE阻止默认行为
addEvent.fixEvent.preventDefault = function () {
this.returnValue = false;
};
//IE取消冒泡
addEvent.fixEvent.stopPropagation = function () {
this.cancelBubble = true;
};
//跨浏览器删除事件
function removeEvent(obj, type, fn) {
if (typeof obj.removeEventListener != 'undefined') {
obj.removeEventListener(type, fn, false);
} else {
for (var i in obj.events[type]) {
if (obj.events[type][i] == fn) {
delete obj.events[type][i];
}
}
}
}
html的代码:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="Base.js"></script>
<script type="text/javascript" src="demo3.js"></script>
<script type="text/javascript">
</script>
</head>
<body>
<input type="button" value="按钮" id="button" />
<a href="http://www.baidu.com" id="a">百度一下</a>
</body>
</html>
demo.js的代码:
window.onload = function () {
var oButton = document.getElementById('button');
/*
addEvent(oButton, 'click', fn1);
addEvent(oButton, 'click', fn2);
addEvent(oButton, 'click', fn3);
removeEvent(oButton, 'click', fn2);
*/
var a = document.getElementById('a');
addEvent(a, 'click', function (e) {
e.preventDefault();
});
addEvent(oButton, 'click', function (e) {
e.stopPropagation();
alert('button');
});
addEvent(document, 'click', function () {
alert('document');
});
};
function fn1(e) {
alert('1' + this.value + e.clientX);
}
function fn2(e) {
alert('2' + this.value + e.clientX);
}
function fn3(e) {
alert('3' + this.value + e.clientX);
}
浏览器检测:
//浏览器检测
/*
function getState() {
alert('');
};
getState(); //需要调用一下,比较多余
*/
//alert(''); //直接写到全局里,比较混乱
/*
(function getState() { //闭包
alert('');
})();
*/
(function () {
window.sys = {}; //让外部可以访问,保存浏览器信息对象
var ua = navigator.userAgent.toLowerCase(); //获取浏览器信息字符串
var s; //浏览器信息数组,浏览器名称+版本
//alert(ua);
//alert(ua.match(/msie ([\d.]+)/)); //msie 7.0,7.0
//alert(ua.match(/firefox\/([\d.]+)/)); //firefox/3.6.28,3.6.28
//alert(ua.match(/chrome\/([\d.]+)/));
//alert(window.opera.version());
//alert(ua.match(/opera\/.*version\/([\d.]+)/));
//alert(ua.match(/version\/([\d.]+).*safari/));
/*
if ((/msie ([\d.]+)/).test(ua)) {
s = ua.match(/msie ([\d.]+)/);
sys.ie = s[1];
}
if ((/firefox\/([\d.]+)/).test(ua)) {
s = ua.match(/firefox\/([\d.]+)/);
sys.firefox = s[1];
}
if ((/chrome\/([\d.]+)/).test(ua)) {
s = ua.match(/chrome\/([\d.]+)/);
sys.chrome = s[1];
}
if ((/opera\/.*version\/([\d.]+)/).test(ua)) {
s = ua.match(/opera\/.*version\/([\d.]+)/);
sys.opera = s[1];
}
if ((/version\/([\d.]+).*safari/).test(ua)) {
s = ua.match(/version\/([\d.]+).*safari/);
sys.safari = s[1];
}
*/
(s = ua.match(/msie ([\d.]+)/)) ? sys.ie = s[1] :
(s = ua.match(/firefox\/([\d.]+)/)) ? sys.firefox = s[1] :
(s = ua.match(/chrome\/([\d.]+)/)) ? sys.chrome = s[1] :
(s = ua.match(/opera\/.*version\/([\d.]+)/)) ? sys.opera = s[1] :
(s = ua.match(/version\/([\d.]+).*safari/)) ? sys.safari = s[1] : 0;
})();