`
adezuo
  • 浏览: 6950 次
  • 性别: Icon_minigender_1
  • 来自: 河南
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

(转)精通JavaScript DOM事件

阅读更多
事件(上)


JavaScript事件列表
事件 解说
一般事件 onclick 鼠标点击时触发此事件
ondblclick 鼠标双击时触发此事件
onmousedown 按下鼠标时触发此事件
onmouseup 鼠标按下后松开鼠标时触发此事件
onmouseover 当鼠标移动到某对象范围的上方时触发此事件
onmousemove 鼠标移动时触发此事件
onmouseout 当鼠标离开某对象范围时触发此事件
onkeypress 当键盘上的某个键被按下并且释放时触发此事件.
onkeydown 当键盘上某个按键被按下时触发此事件
onkeyup 当键盘上某个按键被按放开时触发此事件
页面相关事件 onabort 图片在下载时被用户中断
onbeforeunload 当前页面的内容将要被改变时触发此事件
onerror 出现错误时触发此事件
onload 页面内容完成时触发此事件
onmove 浏览器的窗口被移动时触发此事件
onresize 当浏览器的窗口大小被改变时触发此事件
onscroll 浏览器的滚动条位置发生变化时触发此事件
onstop 浏览器的停止按钮被按下时触发此事件或者正在下载的文件被中断
oncontextmenu 当弹出右键上下文菜单时发生
onunload 当前页面将被改变时触发此事件
表单相关事件 onblur 当前元素失去焦点时触发此事件
onchange 当前元素失去焦点并且元素的内容发生改变而触发此事件
onfocus 当某个元素获得焦点时触发此事件
onreset 当表单中RESET的属性被激发时触发此事件
onsubmit 一个表单被递交时触发此事件

了解上面的事件如此简单,那么事件还有什么可讲的呢?

问题一:每个事件只能注册一个函数





Js代码 1.var oDiv = document.getElementById("oDiv"); 
2.oDiv.onclick = fn1; 
3.oDiv.onclick =fn2; 
4.function fn1() {alert("我被覆盖了!")} 
5.function fn2() {alert("只有我被执行到!")} 
var oDiv = document.getElementById("oDiv");
oDiv.onclick = fn1;
oDiv.onclick =fn2;
function fn1() {alert("我被覆盖了!")}
function fn2() {alert("只有我被执行到!")} 




解决方案一:





Js代码 1.obj.onclick = function () { 
2.    fn1(); 
3.    fn2(); 
4.    fn3(); 
5.}; 
obj.onclick = function () {
fn1();
fn2();
fn3();
}; 






缺陷一:需要将所有函数一次添加进去,不能在运行时添加

缺陷二:在事件处理函数中this将指向window,而不是obj

解决方案二:





Js代码 1.function addEvent(fn,evtype,obj) { 
2.    //obj是要添加事件的HTML元素对象 
3.    //evtype是事件名字,不包含on前缀,因为每个都有on,所以写个on是多余的 
4.    //fn是事件处理函数 
5.    var oldFn; 
6.    if (obj["on"+evtype] instanceof Function) { 
7.        oldFn = obj["on"+evtype];//当添加函数时,如果已注册过了,则将其保存起来 
8.    } 
9.    obj["on"+evtype]=function () { 
10.            if (oldFn) { 
11.                oldFn.call(this); 
12.            } 
13.            fn.call(this);//使用call方法,使事件处理函数中的this仍指向obj 
14.    }; 
15.} 
function addEvent(fn,evtype,obj) {
//obj是要添加事件的HTML元素对象
//evtype是事件名字,不包含on前缀,因为每个都有on,所以写个on是多余的
//fn是事件处理函数
var oldFn;
if (obj["on"+evtype] instanceof Function) {
oldFn = obj["on"+evtype];//当添加函数时,如果已注册过了,则将其保存起来
}
obj["on"+evtype]=function () {
if (oldFn) {
oldFn.call(this);
}
fn.call(this);//使用call方法,使事件处理函数中的this仍指向obj
};





这样已经解决了问题,但如何删除事件呢?如果直接将对象的onevtype这类的属性赋值为null将会删除所有的事件处理函数!

解决方案二的修改版:先将事件存储起来,存储在对象的__EventHandles属性里面





Js代码 1.eventHandlesCounter=1;//计数器,将统计所有添加进去的函数的个数,0位预留作其它用 
2.function addEvent(fn,evtype,obj) { 
3.    if (!fn.__EventID) {//__EventID是给函数加的一个标识,见下面给函数添加标识的部分 
4.        fn.__EventID=eventHandlesCounter++; 
5.        //使用一个自动增长的计数器作为函数的标识以保证不会重复 
6.    } 
7.    if (!obj.__EventHandles) { 
8.        obj.__EventHandles=[];//当不存在,也就是第一次执行时,创建一个,并且是数组 
9.    } 
10.    if (!obj.__EventHandles[evtype]) {//将所有事件处理函数按事件类型分类存放 
11.        obj.__EventHandles[evtype]={};//当不存在时也创建一个散列表 
12.                      if (obj["on"+evtype] instanceof Function) { 
13.            //查看是否已经注册过其它函数 
14.            //如果已经注册过,则将以前的事件处理函数添加到下标为0的预留的位置 
15.            obj.__EventHandles[evtype][0]=obj["on"+evtype]; 
16.            obj["on"+evtype]=handleEvents;//使用handleEvents集中处理所有的函数 
17.        } 
18.    } 
19.    obj.__EventHandles[evtype][fn.__EventID]=fn; 
20.    //如果函数是第一次注册为事件处理函数,那么它将被添加到表中,函数的标识作为下标 
21.    //如果函数已经注册过相同对象的相同事件了,那么将覆盖原来的而不会被添加两次 
22.    function handleEvents() { 
23.        var fns = obj.__EventHandles[evtype]; 
24.        for (var i in fns) { 
25.            fns[i].call(this); 
26.        } 
27.    } 
28.} 
eventHandlesCounter=1;//计数器,将统计所有添加进去的函数的个数,0位预留作其它用
function addEvent(fn,evtype,obj) {
if (!fn.__EventID) {//__EventID是给函数加的一个标识,见下面给函数添加标识的部分
fn.__EventID=eventHandlesCounter++;
//使用一个自动增长的计数器作为函数的标识以保证不会重复
}
if (!obj.__EventHandles) {
obj.__EventHandles=[];//当不存在,也就是第一次执行时,创建一个,并且是数组
}
if (!obj.__EventHandles[evtype]) {//将所有事件处理函数按事件类型分类存放
obj.__EventHandles[evtype]={};//当不存在时也创建一个散列表
                       if (obj["on"+evtype] instanceof Function) {
//查看是否已经注册过其它函数
//如果已经注册过,则将以前的事件处理函数添加到下标为0的预留的位置
obj.__EventHandles[evtype][0]=obj["on"+evtype];
obj["on"+evtype]=handleEvents;//使用handleEvents集中处理所有的函数
}
}
obj.__EventHandles[evtype][fn.__EventID]=fn;
//如果函数是第一次注册为事件处理函数,那么它将被添加到表中,函数的标识作为下标
//如果函数已经注册过相同对象的相同事件了,那么将覆盖原来的而不会被添加两次
function handleEvents() {
var fns = obj.__EventHandles[evtype];
for (var i in fns) {
fns[i].call(this);
}
}





使用上面的函数已经可以在一个对象添加多个事件处理函数,在函数内部this关键字也指向了相应的对象,并且这些函数都被作了标识,那么移除某个事件处理函数就是轻而易举的了!





Js代码 1.//使用传统方法:obj.onevtype = null;但这样会移除所有的事件处理函数 
2.    function delEvent(fn,evtype,obj) { 
3.        if (!obj.__EventHandles || !obj.__EventHandles[evtype] || !fn.__EventID) { 
4.            return false; 
5.        } 
6.        if (obj.__EventHandles[evtype][fn.__EventID] == fn) { 
7.            delete obj.__EventHandles[evtype][fn.__EventID]; 
8.        } 
9.    } 
//使用传统方法:obj.onevtype = null;但这样会移除所有的事件处理函数
function delEvent(fn,evtype,obj) {
if (!obj.__EventHandles || !obj.__EventHandles[evtype] || !fn.__EventID) {
return false;
}
if (obj.__EventHandles[evtype][fn.__EventID] == fn) {
delete obj.__EventHandles[evtype][fn.__EventID];
}
}











-------------------------------------------------新手的分隔线----------------------------------------------------------------





事件(下)
事件对象——Event
事件对象是用来记录一些事件发生时的相关信息的对象。事件对象只有事件发生时才会产生,并且只能是事件处理函数内部访问,在所有事件处理函数运行结束后,事件对象就被销毁!

访问事件对象:W3C DOM方法与IE专用方法


Js代码 1.//W3C DOM把事件对象作为事件处理函数的第一个参数传入进去 
2.    document.onclick = function (evt) {//这样,事件对象只能在对应的事件处理函数内部可以访问到 
3.        alert(evt); 
4.    }; 
5.    //IE将事件对象作为window对象的一个属性(相当于全局变量) 
6.    //貌似全局对象,但是只有是事件发生时才能够访问 
7.    alert(window.event);//null 
8.    window.onload = function () { 
9.        alert(window.event); 
10.    }; 
//W3C DOM把事件对象作为事件处理函数的第一个参数传入进去
document.onclick = function (evt) {//这样,事件对象只能在对应的事件处理函数内部可以访问到
alert(evt);
};
//IE将事件对象作为window对象的一个属性(相当于全局变量)
//貌似全局对象,但是只有是事件发生时才能够访问
alert(window.event);//null
window.onload = function () {
alert(window.event);
}; 




事件对象的属性及方法

鼠标相关 属性名 值类型 读/写 描述
button Integer R 对于特定的鼠标事件,表示按下的鼠标按钮,该属性仅可以在mouseup与mousedown事件中访问。W3C 规定:0表示按下了左键,1表示按下了中键,2表示按下了右键,相当于对于鼠标键从左到右进行的编号,而编号从0开始; 而IE有另外一套规定:0表示没有任何键按下,1表示左键,2表示右键,4表示中键,而其它按键的组合则只要将键码相加即可,如:同时按下左右键时button值为3

clientX Integer R 事件发生时,鼠标在客户端区域的X坐标,客户端区域是指页面可视区域
clientY Integer R 事件发生时,鼠标在客户端区域的Y坐标
screenX Integer R(IE) R/W(W3C) 相对于屏幕的鼠标X坐标
screenY Integer R(IE) R/W(W3C) 相对于屏幕的鼠标Y坐标
x(仅IE) Integer R 鼠标相对于引起事件的元素的父元素的X坐标
y(仅IE) Integer R 鼠标相对于引起事件的元素的父元素的Y坐标
offsetX(仅IE) layerX(仅W3C) Integer R 鼠标相对于引起事件的对象的X坐标
offsetY(仅IE) layerY(仅W3C) Integer R 鼠标相对于引起事件的对象的Y坐标
pageX(仅W3C) Integer R 鼠标相对于页面的X坐标
pageY(仅W3C) Integer R 鼠标相对于页面的Y坐标
键盘相关 属性名 值类型 读/写 描述
altKey Boolean R true表示按下了ALT键;false表示没有按下
ctrlKey Boolean R true表示按下了CTROL,false表示没有
shiftKey Boolean R true表示按下了shift,false表示没有
keyCode Integer R/W(IE) R(W3C) 对于keypress事件,表示按下按钮的Unicode字符;对于keydown/keyup事件 ,表示按下按钮的数字代号
charCode(仅W3C) Integer R 在keypress事件中所按键的字符Unicode编码,如果不是字符键,则该属性为0,并且,当CapsLock打开与关闭时charCode的值也对应着大小写字母
其它 属性名 值类型 读/写 描述
srcElement(IE) target(W3C) Element R 引起事件的元素
fromElement(仅IE) Element R 某些鼠标事件中(mouseover与mouseout),鼠标所离开的元素
toElement(仅IE) Element R 某些鼠标事件中(mouseover与mouseout),鼠标所进入的元素
relatedTarget(仅W3C) Element R 某些鼠标事件中(mouseover与mouseout),返回与事件的目标节点相关的节点。
repeat(仅IE) Boolean R 如果不断触发keydown事件,则为true,否则为false
returnValue(仅IE) Boolean R/W 将其设为false表示以取消事件的默认动作
preventDefault(仅W3C) Function R 执行方法以取消事件的默认动作
type String R 事件的名称,不带on前缀
cancelable(仅W3C ) Boolean R 当为true表示事件的默认动作可以被取消(用preventDefault方法取消)
cancelBubble(仅IE) Boolean R/W 将其设置为true将取消事件冒泡
stopPropagation(仅W3C) Function R 执行方法取消事件冒泡
bubbles(仅W3C) Boolean R 返回true表示事件是冒泡类型
eventPhase(仅W3C) Integer R 返回事件传播的当前阶段。它的值是下面的三个常量之一,它们分别表示捕获阶段、在目标对象上时和起泡阶段: 常量 值
Event.CAPTURING_PHASE(捕获阶段) 1
Event.AT_TARGET(在目标对象上) 2
Event.BUBBLING_PHASE(冒泡阶段) 3

timeStamp (仅W3C) Long R 返回一个时间戳。指示发生事件的日期和时间(从 epoch 开始的毫秒数)。epoch 是一个事件参考点。在这里,它是客户机启动的时间。并非所有系统都提供该信息,因此,timeStamp 属性并非对所有系统/事件都是可用的。

取得事件对象及取得事件目标对象





Js代码 1.document.onclick =function (evt) { 
2.        evt = evt || window.event;//在IE中evt会是undefined 
3.        //而支持W3C DOM事件的浏览器中事件对象将会作为事件处理函数的第一个参数 
4.        var targetElement = evt.target || evt.srcElement; 
5.        //IE中事件对象没有target属性 
6.    }; 
document.onclick =function (evt) {
evt = evt || window.event;//在IE中evt会是undefined
//而支持W3C DOM事件的浏览器中事件对象将会作为事件处理函数的第一个参数
var targetElement = evt.target || evt.srcElement;
//IE中事件对象没有target属性
}; 






阻止事件发生时浏览器的默认行为





Js代码 1.document.onclick = function (evt) { 
2.    evt = evt || window.event; 
3.    var target = evt.target || evt.srcElement; 
4.    if (!target) { 
5.        return; 
6.    } 
7.    if (target.tagName=="A" && target.href) { 
8.        //使用传统的方法取消事件默认行为必须使用return false 
9.        //但使用了return ,函数便终止了运行,可以使用事件对象来取消 
10.        if (window.event) {//IE 
11.            window.event.returnValue = false; 
12.        } else { 
13.            evt.preventDefault(); 
14.        } 
15.        window.open(target.href,"newWindow"); 
16.        //这样让所有的链接在新窗口打开 
17.    } 
18.}; 
document.onclick = function (evt) {
evt = evt || window.event;
var target = evt.target || evt.srcElement;
if (!target) {
return;
}
if (target.tagName=="A" && target.href) {
//使用传统的方法取消事件默认行为必须使用return false
//但使用了return ,函数便终止了运行,可以使用事件对象来取消
if (window.event) {//IE
window.event.returnValue = false;
} else {
evt.preventDefault();
}
window.open(target.href,"newWindow");
//这样让所有的链接在新窗口打开
}
};
 






事件传播——冒泡与捕获

DOM事件标准定义了两种事件流,这两种事件流有着显著的不同并且可能对你的应用有着相当大的影响。这两种事件流分别是捕获和冒泡。和许多Web技术一样,在它们成为标准之前,Netscape和微软各自不同地实现了它们。Netscape选择实现了捕获事件流,微软则实现了冒泡事件流。幸运的是,W3C决定组合使用这两种方法,并且大多数新浏览器都遵循这两种事件流方式。

默认情况下,事件使用冒泡事件流,不使用捕获事件流。然而,在Firefox和Safari里,你可以显式的指定使用捕获事件流,方法是在注册事件时传入useCapture参数,将这个参数设为true。

冒泡事件流
当事件在某一DOM元素被触发时,例如用户在客户名字节点上点击鼠标,事件将跟随着该节点继承自的各个父节点冒泡穿过整个的DOM节点层次,直到它遇到依附有该事件类型处理器的节点,此时,该事件是onclick事件。在冒泡过程中的任何时候都可以终止事件的冒泡,在遵从W3C标准的浏览器里可以通过调用事件对象上的stopPropagation()方法,在Internet Explorer里可以通过设置事件对象的cancelBubble属性为true。如果不停止事件的传播,事件将一直通过DOM冒泡直至到达文档根。

捕获事件流
事件的处理将从DOM层次的根开始,而不是从触发事件的目标元素开始,事件被从目标元素的所有祖先元素依次往下传递。在这个过程中,事件会被从文档根到事件目标元素之间各个继承派生的元素所捕获,如果事件监听器在被注册时设置了useCapture属性为true,那么它们可以被分派给这期间的任何元素以对事件做出处理;否则,事件会被接着传递给派生元素路径上的下一元素,直至目标元素。事件到达目标元素后,它会接着通过DOM节点再进行冒泡。

现代事件绑定方法
针对如上节课所讨论的,使用传统事件绑定有许多缺陷,比如不能在一个对象的相同事件上注册多个事件处理函数。而浏览器和W3C也并非没有考虑到这一点,因此在现代浏览器中,它们有自己的方法绑定事件。

W3C DOM

•obj.addEventListener(evtype,fn,useCapture)——W3C提供的添加事件处理函数的方法。obj是要添加事件的对象,evtype是事件类型,不带on前缀,fn是事件处理函数,如果useCapture是true,则事件处理函数在捕获阶段被执行,否则在冒泡阶段执行
•obj.removeEventListener(evtype,fn,useCapture)——W3C提供的删除事件处理函数的方法
微软IE方法

•obj.attachEvent(evtype,fn)——IE提供的添加事件处理函数的方法。obj是要添加事件的对象,evtype是事件类型,带on前缀,fn是事件处理函数,IE不支持事件捕获
•obj.detachEvent(evtype,fn,)——IE提供的删除事件处理函数的方法,evtype包含on前缀
整合两者的方法





Js代码 1.function addEvent(obj,evtype,fn,useCapture) { 
2.    if (obj.addEventListener) { 
3.        obj.addEventListener(evtype,fn,useCapture); 
4.    } else { 
5.        obj.attachEvent("on"+evtype,fn);//IE不支持事件捕获 
6.    } else { 
7.        obj["on"+evtype]=fn;//事实上这种情况不会存在 
8.    } 
9.} 
10.function delEvent(obj,evtype,fn,useCapture) { 
11.    if (obj.removeEventListener) { 
12.        obj.removeEventListener(evtype,fn,useCapture); 
13.    } else { 
14.        obj.detachEvent("on"+evtype,fn); 
15.    } else { 
16.        obj["on"+evtype]=null; 
17.    } 
18.} 
function addEvent(obj,evtype,fn,useCapture) {
if (obj.addEventListener) {
obj.addEventListener(evtype,fn,useCapture);
} else {
obj.attachEvent("on"+evtype,fn);//IE不支持事件捕获
} else {
obj["on"+evtype]=fn;//事实上这种情况不会存在
}
}
function delEvent(obj,evtype,fn,useCapture) {
if (obj.removeEventListener) {
obj.removeEventListener(evtype,fn,useCapture);
} else {
obj.detachEvent("on"+evtype,fn);
} else {
obj["on"+evtype]=null;
}







其它兼容性问题:IE不支持事件捕获?很抱歉,这个没有办法解决!但IE的attach方法有个问题,就是使用attachEvent时在事件处理函数内部,this指向了window,而不是obj!当然,这个是有解决方案的!





Js代码 1.function addEvent(obj,evtype,fn,useCapture) { 
2.        if (obj.addEventListener) { 
3.            obj.addEventListener(evtype,fn,useCapture); 
4.        } else { 
5.            obj.attachEvent("on"+evtype,function () { 
6.                fn.call(obj); 
7.            }); 
8.        } else { 
9.            obj["on"+evtype]=fn;//事实上这种情况不会存在 
10.        } 
11.    } 
function addEvent(obj,evtype,fn,useCapture) {
if (obj.addEventListener) {
obj.addEventListener(evtype,fn,useCapture);
} else {
obj.attachEvent("on"+evtype,function () {
fn.call(obj);
});
} else {
obj["on"+evtype]=fn;//事实上这种情况不会存在
}





但IE的attachEvent方法有另外一个问题,同一个函数可以被注册到同一个对象同一个事件上多次,解决方法:抛弃IE的 attachEvent方法吧!IE下的attachEvent方法不支持捕获,和传统事件注册没多大区别(除了能绑定多个事件处理函数),并且IE的 attachEvent方法存在内存泄漏问题!

addEvent,delEvent现代版





Js代码 1.function addEvent(obj,evtype,fn,useCapture) { 
2.    if (obj.addEventListener) {//优先考虑W3C事件注册方案 
3.        obj.addEventListener(evtype,fn,!!useCapture); 
4.    } else {//当不支持addEventListener时(IE),由于IE同时也不支持捕获,所以不如使用传统事件绑定 
5.        if (!fn.__EventID) {fn.__EventID = addEvent.__EventHandlesCounter++;} 
6.        //为每个事件处理函数分配一个唯一的ID 
7.         
8.        if (!obj.__EventHandles) {obj.__EventHandles={};} 
9.        //__EventHandles属性用来保存所有事件处理函数的引用 
10.         
11.        //按事件类型分类 
12.        if (!obj.__EventHandles[evtype]) {//第一次注册某事件时 
13.            obj.__EventHandles[evtype]={}; 
14.            if (obj["on"+evtype]) {//以前曾用传统方式注册过事件处理函数 
15.                (obj.__EventHandles[evtype][0]=obj["on"+evtype]).__EventID=0;//添加到预留的0位 
16.                //并且给原来的事件处理函数增加一个ID 
17.            } 
18.            obj["on"+evtype]=addEvent.execEventHandles; 
19.            //当事件发生时,execEventHandles遍历表obj.__EventHandles[evtype]并执行其中的函数 
20.        } 
21.    } 
22.} 
23.addEvent.__EventHandlesCounter=1;//计数器,0位预留它用 
24.addEvent.execEventHandles = function (evt) {//遍历所有的事件处理函数并执行 
25.    if (!this.__EventHandles) {return true;} 
26.    evt = evt || window.event; 
27.    var fns = this.__EventHandles[evt.type]; 
28.    for (var i in fns) { 
29.            fns[i].call(this); 
30.    } 
31.}; 
32.function delEvent(obj,evtype,fn,useCapture) { 
33.    if (obj.removeEventListener) {//先使用W3C的方法移除事件处理函数 
34.        obj.removeEventListener(evtype,fn,!!useCapture); 
35.    } else { 
36.        if (obj.__EventHandles) { 
37.            var fns = obj.__EventHandles[evtype]; 
38.            if (fns) {delete fns[fn.__EventID];} 
39.        } 
40.    } 
41.} 
function addEvent(obj,evtype,fn,useCapture) {
if (obj.addEventListener) {//优先考虑W3C事件注册方案
obj.addEventListener(evtype,fn,!!useCapture);
} else {//当不支持addEventListener时(IE),由于IE同时也不支持捕获,所以不如使用传统事件绑定
if (!fn.__EventID) {fn.__EventID = addEvent.__EventHandlesCounter++;}
//为每个事件处理函数分配一个唯一的ID

if (!obj.__EventHandles) {obj.__EventHandles={};}
//__EventHandles属性用来保存所有事件处理函数的引用

//按事件类型分类
if (!obj.__EventHandles[evtype]) {//第一次注册某事件时
obj.__EventHandles[evtype]={};
if (obj["on"+evtype]) {//以前曾用传统方式注册过事件处理函数
(obj.__EventHandles[evtype][0]=obj["on"+evtype]).__EventID=0;//添加到预留的0位
//并且给原来的事件处理函数增加一个ID
}
obj["on"+evtype]=addEvent.execEventHandles;
//当事件发生时,execEventHandles遍历表obj.__EventHandles[evtype]并执行其中的函数
}
}
}
addEvent.__EventHandlesCounter=1;//计数器,0位预留它用
addEvent.execEventHandles = function (evt) {//遍历所有的事件处理函数并执行
if (!this.__EventHandles) {return true;}
evt = evt || window.event;
var fns = this.__EventHandles[evt.type];
for (var i in fns) {
fns[i].call(this);
}
};
function delEvent(obj,evtype,fn,useCapture) {
if (obj.removeEventListener) {//先使用W3C的方法移除事件处理函数
obj.removeEventListener(evtype,fn,!!useCapture);
} else {
if (obj.__EventHandles) {
var fns = obj.__EventHandles[evtype];
if (fns) {delete fns[fn.__EventID];}
}
}
}
 




标准化事件对象

IE的事件对象与W3C DOM的事件对象有许多不一样的地方,解决的最好的方法就是调整IE的事件对象,以使它尽可能的与标准相似!下表列出了IE事件对象中一些和W3C DOM名称或值不一样但含义相同的属性

IE与W3C DOM事件对象的不同 W3C DOM IE
button——按键编码为:0-左键,1-中键,2-右键 button——按键编码为:1-左键,2-右键,4-中键
charCode 没有对应属性,但可以用keyCode来代替
preventDefault 没有对应方法,但可以将event对象的returnValue设为false来模拟
target srcElement
relatedTarget fromElement与toElement
stopPropagation 没有对应方法,但可以通过将event对象的cancelBubble属性设为true来模拟







总结出fixEvent函数





Js代码 1.function fixEvent(evt) { 
2.    if (!evt.target) { 
3.        evt.target = evt.srcElement; 
4.        evt.preventDefault = fixEvent.preventDefault; 
5.        evt.stopPropagation = fixEvent.stopPropagation; 
6.        if (evt.type == "mouseover") { 
7.            evt.relatedTarget = evt.fromElement; 
8.        } else if (evt.type =="mouseout") { 
9.            evt.relatedTarget = evt.toElement; 
10.        } 
11.        evt.charCode =  (evt.type=="keypress")?evt.keyCode:0; 
12.        evt.eventPhase = 2;//IE仅工作在冒泡阶段 
13.        evt.timeStamp = (new Date()).getTime();//仅将其设为当前时间 
14.    } 
15.    return evt; 
16.} 
17.fixEvent.preventDefault =function () { 
18.    this.returnValue = false;//这里的this指向了某个事件对象,而不是fixEvent 
19.}; 
20.fixEvent.stopPropagation =function () { 
21.    this.cancelBubble = true; 
22.}; 
function fixEvent(evt) {
if (!evt.target) {
evt.target = evt.srcElement;
evt.preventDefault = fixEvent.preventDefault;
evt.stopPropagation = fixEvent.stopPropagation;
if (evt.type == "mouseover") {
evt.relatedTarget = evt.fromElement;
} else if (evt.type =="mouseout") {
evt.relatedTarget = evt.toElement;
}
evt.charCode =  (evt.type=="keypress")?evt.keyCode:0;
evt.eventPhase = 2;//IE仅工作在冒泡阶段
evt.timeStamp = (new Date()).getTime();//仅将其设为当前时间
}
return evt;
}
fixEvent.preventDefault =function () {
this.returnValue = false;//这里的this指向了某个事件对象,而不是fixEvent
};
fixEvent.stopPropagation =function () {
this.cancelBubble = true;
}; 


fixEvent函数不是单独执行的,它必须有一个事件对象参数,而且只有事件发生时它才被执行!最好的方法是把它整合到addEvent函数的execEventHandles里面







Js代码 1.addEvent.execEventHandles = function (evt) {//遍历所有的事件处理函数并执行 
2.    if (!this.__EventHandles) {return true;} 
3.    evt = fixEvent(evt || window.event);//在这里对其进行标准化操作 
4.    var fns = this.__EventHandles[evt.type]; 
5.    for (var i in fns) { 
6.            fns[i].call(this,evt);//并且将其作为事件处理函数的第一个参数 
7.            //这样在事件处理函数内部就可以使用统一的方法访问事件对象了 
8.    } 
9.}; 
addEvent.execEventHandles = function (evt) {//遍历所有的事件处理函数并执行
if (!this.__EventHandles) {return true;}
evt = fixEvent(evt || window.event);//在这里对其进行标准化操作
var fns = this.__EventHandles[evt.type];
for (var i in fns) {
fns[i].call(this,evt);//并且将其作为事件处理函数的第一个参数
//这样在事件处理函数内部就可以使用统一的方法访问事件对象了
}
}; 




Load事件

使用JavaScript操纵DOM,必须等待DOM加载完毕才可以执行代码,但window.onload有个坏处,它非要等到页面中的所有图片及视频加载完毕才会触发load事件。结果就是一些本来应该在打开时隐藏起来的元素,由于网络延迟,在页面打开时仍然会出现,然后又会突然消失,让用户觉得莫名其妙。



大师们想出来的方法:





Js代码 1.function addLoadEvent(fn) { 
2.    var init = function() { 
3.        if (arguments.callee.done) return; 
4.        arguments.callee.done = true; 
5.        fn.apply(document,arguments); 
6.    }; 
7.    //注册DOMContentLoaded事件,如果支持的话 
8.    if (document.addEventListener) { 
9.        document.addEventListener("DOMContentLoaded", init, false); 
10.    } 
11.    //但对于Safari,我们需要使用setInterval方法不断检测document.readyState 
12.    //当为loaded或complete的时候表明DOM已经加载完毕 
13.    if (/WebKit/i.test(navigator.userAgent)) { 
14.        var _timer = setInterval(function() { 
15.            if (/loaded|complete/.test(document.readyState)) { 
16.                clearInterval(_timer); 
17.                init(); 
18.            } 
19.        },10); 
20.    } 
21.    //对于IE则使用条件注释,并使用script标签的defer属性 
22.    //IE中可以给script标签添加一个defer(延迟)属性,这样,标签中的脚本只有当DOM加载完毕后才执行 
23.    /*@cc_on @*/ 
24.    /*@if (@_win32)
25.    document.write("<script id=\"__ie_onload\" defer=\"defer\" src=\"javascript:void(0)\"><\/script>");
26.    var script = document.getElementById("__ie_onload");
27.    script.onreadystatechange = function() {
28.        if (this.readyState == "complete") {
29.            init();
30.        }
31.    };
32.    /*@end @*/ 
33.    return true; 
34. } 
分享到:
评论

相关推荐

    JavaScript DOM编程艺术【第2版&高清】.pdf

    5. DOM事件处理:JavaScript通过事件驱动进行交互。事件会在特定的动作(如点击、按键、加载等)发生时被触发,DOM提供了添加和移除事件监听器的接口。学习如何在DOM元素上绑定事件和编写事件处理函数是提高网页交互...

    精通JavaScript(源代码) jQuery之父John Resig所写

    《精通JavaScript(源代码)》是由jQuery之父John Resig撰写的高级JavaScript技术书籍,它不仅深入探讨了JavaScript的核心概念,而且重点解析了jQuery库的内部工作机制,为读者揭示了JavaScript编程的深层次奥秘。...

    精通JavaScript源代码.rar

    《精通JavaScript》这本书深入浅出地介绍了JavaScript的各个方面,旨在帮助读者从新手进阶到高级开发者。其附带的源代码压缩包“精通JavaScript.rar”包含了381个示例,覆盖了书中讲解的各种技术点。 在JavaScript...

    精通javascript+jQuery

    《精通JavaScript+jQuery》从JavaScript的基础知识开始,围绕标准Web的各项技术予以展开,通过大量实例对JavaScript、CSS、DOM、Ajax等Web关键技术进行深入浅出的分析。主要内容包括JavaScript的概念和基本语法、CSS...

    《精通JavaScript》

    ### 精通JavaScript #### 一、JavaScript简介与历史 JavaScript是一种广泛使用的脚本语言,在Web开发领域占据着举足轻重的地位。它最初由网景公司在1995年设计并实现,并且在ECMA国际组织的支持下,成为了一种标准...

    精通JavaScript(中文清晰优化版)

    精通JavaScript意味着能够熟练地运用它来创建交互式、动态的网页内容,提升用户体验,实现复杂的功能。这份“精通JavaScript(中文清晰优化版)”的资源,显然是为了帮助开发者深入理解和掌握这门语言,提供了中文...

    jQuery动画特效---精通JavaScript+jQuery

    第6课 - JavaScript事件 - [精通JavaScript+jQuery] 第7课 - 表格与表单 - [精通JavaScript+jQuery] 第8课 - Javascript调试与优化 - [精通JavaScript+jQuery] 第9课 - Ajax - [精通JavaScript+jQuery] jQuery...

    JavaScriptDOM编程艺术

    7. **事件冒泡与事件捕获**:在DOM事件处理中,事件会从最深的节点向上冒泡到根节点,也可以自顶向下捕获。理解和掌握这两个机制对于优化事件处理和防止重复触发至关重要。 8. **异步编程**:在现代Web开发中,非...

    精通JavaScriptPDF版本下载.txt

    根据提供的文件信息,我们可以推断出这是一份关于《精通JavaScript》这本书的PDF版本下载链接。但是,为了更好地满足您的需求,我将基于这个主题展开更详细的解释与介绍,包括JavaScript的基本概念、特点以及学习...

    精通JavaScript源代码

    要精通JavaScript源代码,我们需要深入理解其核心概念,包括变量、数据类型、作用域、函数、闭包、原型链以及面向对象编程。 首先,JavaScript中的变量通过`var`、`let`或`const`关键字声明,具有动态类型,意味着...

    精通JavaScript.pdf

    在提供的文件"精通JavaScript.jQuery.pdf"中,我们可以期待找到关于JavaScript深入理解和使用jQuery的教程。jQuery的学习将帮助开发者更好地掌握如何利用JavaScript来处理网页交互、动画效果和数据请求。通过学习这...

    精通JavaScript 书籍源代码

    这本书“精通JavaScript”深入探讨了该语言的核心概念和技术,旨在帮助开发者提升技能至专业水平。源代码提供了书中所有实例的实践参考,使得学习过程更加直观和有效。 在“精通JavaScript”中,你可以了解到以下...

    精通JavaScript(John Resig)

    《精通JavaScript》是John Resig所著的一部经典JavaScript教程,尤其因其作者是jQuery的创建者而备受关注。这本书深入浅出地介绍了JavaScript这门语言的各个方面,旨在帮助读者不仅理解JavaScript的基础,还能掌握其...

    精通javascript书及源码

    "精通JavaScript书及源码"这个主题涵盖了深入理解JavaScript语言原理、最佳实践以及实际应用等多个方面。 首先,JavaScript语法基础是所有学习者必须掌握的。这包括变量声明(var、let、const)、数据类型(原始...

    精通Javascript+jQuery视频下载

    它的主要功能包括:DOM 操作(Document Object Model,用于操作页面元素)、事件处理(如点击、滚动等用户交互)、AJAX(Asynchronous JavaScript and XML,实现异步数据交换)以及浏览器兼容性处理等。JavaScript ...

    精通JavaScript+jQuery书中实例

    "精通JavaScript+jQuery"这本书旨在深入解析这两种技术,通过实例帮助读者掌握它们的核心概念和实用技巧。 JavaScript,作为Web的脚本语言,是前端开发的基础。它允许开发者在用户的浏览器上动态更新内容、处理用户...

    精通javascript 源代码

    在"精通JavaScript源代码"的学习过程中,你需要掌握以下几个核心知识点: 1. **基础语法**:包括变量声明(var、let、const)、数据类型(原始类型如字符串、数字、布尔、null、undefined,以及对象类型)、操作符...

    精通JavaScript与jQuery

    JavaScript和jQuery是Web开发中...总之,精通JavaScript与jQuery不仅需要掌握它们的基本语法和核心概念,还需要通过实践不断深化理解和应用能力。这将为你的Web开发生涯打下坚实的基础,并帮助你应对各种网页交互挑战。

    精通JavaScript+JQuery

    《精通JavaScript+JQuery》是曾顺先生撰写的一本深入探讨JavaScript和JQuery技术的书籍,由人民邮电出版社出版。这本书旨在帮助读者全面理解和掌握这两种强大的Web开发工具,从而在网页交互和动态效果实现上达到更高...

    精通JavaScript动态网页编程.rar

    本资源“精通JavaScript动态网页编程”旨在帮助你深入理解和掌握这一核心技术。 首先,JavaScript的核心概念包括变量、数据类型、控制结构(如if语句和循环)、函数以及对象。变量是存储数据的容器,JavaScript有七...

Global site tag (gtag.js) - Google Analytics