javascript事件触发、监听和其游览器兼容问题

写事件处理的时候总是不规范,而且情况不同遇到各种细节问题。把看到的东西记忆整理一下。

  1. 事件触发和监听
  2. event 
  3. 游览器兼容处理

事件触发和监听


javascript中将事件和触发的句柄连接起来,有多种方法。

1)onclick/onmouseover……

这种方法一般比较简单,通过

或者js中为对象添加onclick属性

a.οnclick=function(){do something};

2)addEvent

IE8.0以上和chrome/firefox中可以使用addEventListener来管理事件的触发

除此之外则使用attachEvent

addEventListener(type,handler,method)接收三个值,type为“click,"mouseover"之流,handler为需要运行的函数,method是一个boolean值,false表示冒泡型(bubble),true表示捕获型(capture)。

attachEvent("onclick",handler),因此需要在上面的type前加上字符串“on”

这两个概念就涉及到了js的事件流了。

事件流的概念比较简单。如图所示。

一共有三个阶段:捕获-处理-冒泡。捕获从外层往内,从上往下。而冒泡从下往上,从里往外。

javascript事件触发、监听和其游览器兼容问题_第1张图片

通过以下例子可以看出addEventListener中两种事件流的区别。

设置为获取型(true),则点击图中间的小框,会发现先提示外框再提示里框

当把true改成false之后,则变成冒泡型。

See the Pen eventlistener with bubble by jfc555 (@focusj) on CodePen.


上述两种方法,addEventListener可以对同一个对象反复使用,一个按键添加多个不同的事件触发。而onclick后者相当于对前面的重写,会覆盖掉。


2.evnet和target

一个表格每行末位都添加一个删除按键。如果for循环一个一个添加,效率低而且容易出问题。

而通过监听触发事件的对象,可以将删除按键和该行绑定在一起.

这里要用到event来获取操作触发的事件,target获取操作所在的target对象

function handler(e){
  e=window.event||e;
  target=e.target||e.srcElement;
  if(target.nodeName.toLowerCase==="input"||target.id==="aaa"){
  //do something
  }
}

得到target之后对触发的节点进行判定,执行命令。


实际应用中,假设div元素a中有一个元素b。如果不使用target监测事件对象,则点击b的时候也会触发a的点击事件。跟上面例子一样,点击内部框,外部的框架绑定的handler也会触发。

而用target限制以后,只有点击精确的元素才会触发handler。如假设置外部target.id==="box1"时弹出窗口,则点击box1内部的box2,并不会有什么效果。



3.游览器兼容性处理

首先是addevent的游览器兼容问题,实际上就是addEventListener和attachEvent。

//跨浏览器添加事件
function addHandler(target, eventType, handler) {
  if(target.addEventListener) { //DOM2 events
    target.addEventListener(eventType, handler, false);
  } else if(target.attachEvent){ //IE
    target.attachEvent("on" + eventType, handler);
  }else{
        target["on"+eventType]=handler;//实际上这句并不需要,没有这种情况
   }
}
但是这种处理方式每次调用addHandler的时候都要判定一次,比较浪费资源

因此有两种更好的解决方法。

两种方法都是在判定后重写addHandler,只要调用一次,之后直接使用重写的新函数无需判断。

推荐这种方法(在上面的codepen代码里面就是用这种实现的):

  var addEvent=document.body.addEventListener?
           function(type,handler,method,obj){
		     obj.addEventListener(type,handler,method);
			 console.log("addEventListener");
		   }:
		   function(type,handler,method,obj){
		     obj.attachEvent("on"+type,handler);
			 console.log("attachEvent");
		   }
通过判定document.body上是否存在addEventListener方法来确定使用哪种方法。然后重写addEvent

另一种方法道理上是一样的,但是稍微麻烦一点,借用别人的代码:

//添加事件
function addHandler(target, eventType, handler) {
 
  //检测浏览器类型,并且重写addHanler方法
  if(target.addEventListener) { //DOM2
    addHandler = function(target, eventType, handler) {
      target.addEventListener(eventType, handler, false);
    };
  } else { //IE
    addHandler = function(target, eventType, handler) {
      target.attachEvent("on" + eventType, handler);
    };
  }
  //调用新的函数
  addHandler(target, eventType, handler);
}
最后重写完了调用新函数这个比较容易漏掉。而且效率也不如上面推荐的。


removeEventListener方法也是同理


参考资料:

[1]JavaScript跨浏览器绑定事件函数的优化

[ 2 ]理解DOM中的事件流


你可能感兴趣的:(javascript,web前端)