JS事件绑定及深入

前端之家收集整理的这篇文章主要介绍了JS事件绑定及深入前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

学习要点:

1.传统事件绑定的问题
2.W3C事件处理函数
3.IE事件处理函数
4.事件对象的其他补充

事件绑定分为两种:一种是传统事件绑定(内联模型,脚本模型),一种是现代事件绑定(DOM2级模型)。现代事件绑定在传统绑定上提供了更强大更方便的功能

一 传统事件绑定的问题

传统事件绑定中的内联模型不做讨论,基本很少去用。先来看一下脚本模型,脚本模型将一个函数赋值给一个事件处理函数。传统绑定如:

window.onload=function(){
    var Box=document.getElementById('Box');
    Box.onclick = (){
        alert('Lee');
    };
};

问题一:一个事件处理函数触发两次事件

如果一个页面有两个或者多个js,并且第一个js是第一个程序开发的,第二个js是第二个程序员开发的。第一个window.onload被覆盖了,如

window.onload=(){
    alert('Lee');
};

window.onload=(){
    alert('Mr.lee');
}  

结果只是打印了 Mr.lee

其实是有办法解决这个问题的,看下面这两种形式。
a:

alert(window.onload);//一开始没有注册window.onload,那么就是null

window.onload=);
};

alert(window.onload);如果已经有window.onload,打印的是函数function
);
} 

b:

alert(typeof window.onload);一开始没有window.onolad,旧版火狐显示undefined,新版显示object,
);
};

alert(显示function
);
}

所以解决办法有了。

   window.onload=);
};

if(typeof window.onload=='function'){
    var saved=null;保存上一个事件对象
    saved=window.onload;
}

saved 就是window.onload,saved()相当于window.onload(),但是window.onload()不能执行的
//所以saved()相当于window.onload=function(){}
if(saved){
        saved();执行上一个事件 window.onload=function(){}
    }
    alert('Mr.lee'); 执行本事件
}

问题二:事件切换器
切换一个id为Box的div,让里面的背景red与blue直接切换,并且切换之前弹框一次,如:

window.onload=);
    Box.className="red";
    Box.onclick=(){
        alert('Lee'); 只执行了一次
        blue.call(this);通过匿名函数执行某一函数,那么里面的this就是代表的window,所以可以通过call传递
    };
}

 blue(){
    this.className="blue";
    this.onclick=red;
    
}

 red(){
    this.className="red"blue;
}

上面的代码虽然实现了切换功能,但是弹框只执行了一次。

添加事件函数obj相当于windowtype相当于onloadfn相当于function(){}
 addEvent(obj,type,fn){
    用于保存上一个事件
    nulltypeof obj['on'+type]=='function'){
        saved=obj['on'+type];保存上一个事件
    }
    obj['on'+type]=(){
        (saved){
            saved();
        }
        fn.call(this);
    }
    
}
addEvent(window,'load',var Box=document.getElementById("Box");
    addEvent(Box,'click',function(){ //目的达到,每次都执行了,没有被覆盖
        alert('ss');
    });
    addEvent(Box,'click',blue);
});

;
    addEvent(Box,'click'当不停的切换的时候,浏览器突然卡死,并且报错:too much recursion,太多的递归因为积累了太多的保存的事件解决方案,就是用完的事件,就立刻移除掉

按照上面的代码出现了注释中的错误解决的办法如下:

);
    }
    
}

解决方案,就是用完的事件,就立刻移除掉

移除事件函数
 removeEvent(obj,type){
    if(obj['on'+type]){
        obj['on'+type]=;
    }
}

addEvent(window,1)">;
    removeEvent(this,1)">);
    addEvent(Box,red);
}

二 W3C事件处理函数

addEventListener()与removeEventListener()

W3C事件处理函数两个,addEventListener()removeEventListener()

//W3C自带的两个添加事件和删除事件

1.覆盖问题,解决

window.addEventListener('load',1)">);
},false);

window.addEventListener('load',1)">(){
    alert('Mr.Lee'(){
    alert('Mrs.Lee'false);

2.相同函数屏蔽的问题,解决

window.addEventListener('load',init,1)">);
window.addEventListener('load',1)">);
 init(){
    alert('Lee');
}

3.是否可以传递this,解决
例子1:

window.addEventListener('load',1)">);
    Box.addEventListener('click',1)">(){
        alert();
    },1)">false);

例子2:

window.addEventListener('load',blue,1)">);

this.removeEventListener('click',red,1)">this.addEventListener('click',1)">);
}

);
}

4.添加一个额外的方法,会不会被覆盖,或者只能执行一次,解决

window.addEventListener('load',1)">false);

综上所述:W3C是比较完美的解决了这些问题,非常好用,但是IE8和之前的浏览器并不支持,而是采用了自己的事件,当然IE9已经完全支持了W3C的这两个事件处理函数

W3C可以设置冒泡和捕获方式。

支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,用来设置事件是在事件捕获时执行,还是事件冒泡时执行。而不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,所以把在处理事件时把useCapture设置为false是比较安全,也实现兼容浏览器的效果


事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。
事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签


事件的传播是可以阻止的:
在W3c中,使用stopPropagation()方法
在IE下设置cancelBubble = true

三.IE事件处理函数

attachEvent()detachEvent()

IE实现了与DOM中类似的两个方法detachEvent()。这两个方法接受相同的参数:事件名称函数

在使用这两组函数的时候,先把区别说一下:

@H_141_403@ @H_678_404@1.IE不支持捕获,支持冒泡; @H_678_404@2.IE添加事件不能屏蔽重复的函数; @H_678_404@3.IE中的this指向的是window而不是DOM对象。 @H_678_404@4.在传统事件上,IE是无法接受到event对象的,但使用了attchEvent却可以,但有些区别。

1.覆盖问题,解决了,但有不同,结果是Mrs.Lee,Mr.Lee,最后是Lee

window.attachEvent('onload',1)">);
});

window.attachEvent('onload',1)">);
});
window.attachEvent('onload',1)">);
});

2.相同函数屏蔽的问题,未解决

window.attachEvent('onload');
}

3.是否可以传递this,不能,this指的是window。需要用call方法

window.attachEvent('onload',1)">);
    Box.attachEvent('onclick',1)">alert(this===Box);
        alert(this===window);  true
    });
});

下面还有办法就是通过window.event.srcElement代码如下:

window.attachEvent('onload',1)">);
    Box.attachEvent('onclick'var that=window.event.srcElement;
    that.className="red";
    that.detachEvent('onclick'window.event.srcElement;
    that.className="blue"

4.添加一个额外的方法,会不会被覆盖,或者只能执行一次,解决

在传统绑定上,IE是无法像W3C那样通过传参接受event对象,但是使用attachEvent()却可以。

 window.attachEvent('onload',1)">);
    Box.onclick=function(evt){ 传统方法IE无法通过参数获取evt
        alert(evt);undefined
    }
    Box.attachEvent('onclick',1)">(evt){
        alert(evt);object
        alert(evt.type);click
        alert(evt.srcElement.tagName);DIV
        alert(window.event.srcElement.tagName);DIV
    });
});

跨浏览器的兼容

跨浏览器添加事件

(obj.addEventListener){
        obj.addEventListener(type,1)">);
    }else (obj.attachEvent){
        obj.attachEvent('on'+type,fn);
    }
}

跨浏览器移除事件

(obj.removeEventListener){
        obj.removeEventListener(type,1)">(obj.detachEvent){
        obj.detachEvent('on'+获取目标对象

 getTarget(evt){
    (evt.target){
        return evt.target;
    }(window.event.srcElement){
         window.event.srcElement;
    }
}

调用方式:

addEvent(window,'load',blue);
});


 red(evt){
    getTarget(evt);
    that.className="red";
    removeEvent(that,red);
    addEvent(that,1)"> blue(evt){
    getTarget(evt);
    that.className="blue"四.事件对象的其他补充

relatedTarget事件

w3c中的一个relatedTarget事件。
例如:

addEvent(window,'mouSEOver',1)">(evt){
        alert(evt.relatedTarget); 得到移入Box最近的那个DOM对象
    });
    
    addEvent(Box,'mouSEOut',1)">从Box移出最近的那个DOM对象
    });
});

IE提供了两组分别用于移入移出的属性fromElementtoElement,分别对应mouSEOvermouSEOut

addEvent(window,1)">(){
        alert(window.event.fromElement.tagName); (){
        alert(window.event.toElement.tagName);     });
});

PS:toElement如果分别对应相反的鼠标事件,没有任何意义。

剩下要做的就是跨浏览器兼容操作:

var e=evt || window.event;
    if(e.srcElment){ IE
        if(e.type=='mouSEOver'){
             e.fromElement.tagName;
        }if(e.type="mouSEOut" e.toElement.tagName;
        }
    }if(e.relatedTarget){ w3c
         e.relatedTarget;
    }
}

屏蔽跳转操作

取消事件的默认行为有一种不规范的做法,就是返回false

link.onclick=return ;
}

PS:虽然return false;可以实现这个功能,但是有漏洞。
第一:必须写到最后,这样导致中奖的代码执行后,有可能执行不到return false;
第二:return false 写到最前那么之后的自定义操作就失效了。
所以最好的办法应该是在最前面就阻止默认行为,并且后面的代码还可以执行。

link.onclick=(evt){
    evt.preventDefault;w3c,阻止默认行为
    alert('Lee');
}

link.onclick=(evt){
    window.event.returnValue=false;IE,1)">);
}

那么跨浏览器的兼容:

 preDef(evt){
    (e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue=;
    }
}

右键菜单contextmenu

兼容:

var body=document.getElementsByTagName('body')[0];
    addEvent(body,'contextmenu',1)">(evt){
        preDef(evt);
    })
});

PS:contextmenu事件很常用,这直接导致浏览器兼容性较为稳定。

卸载前事件:beforeunload

这个事件可以帮助在离开本页的时候给出相应的提示,“离开”或者“返回”操作。

addEvent(window,'beforeonload',1)">(){
    preDef(evt);
});

鼠标滚轮(mousewheel)和DOMMouseScroll

用于获取鼠标上下滚轮的距离

addEvent(document,'mousewheel',1)">非火狐
    alert(getWD(evt));
});

addEvent(document,'DOMMouseScroll',1)">火狐
    alert(getWD(evt));
});

 getWD(evt){
    var e=evt||(e.wheelDelta){
         e.wheelDelta;
    }if(e.detail){ 火狐
        return -evt.detail*30;
    }
}

PS:通过浏览器检测可以确定火狐只执行DOMMouseScroll

DOMContentLoaded事件和readystatechange事件

DOMContentLoaded事件和readystatechange事件,有关DOM加载方面的事件。

猜你在找的JavaScript相关文章