浅谈js之事件处理

上一篇是谈的事件流,博客地址:点我;此次咱们说说具体的事件处理。javascript

0x00:事件处理程序html

如今有三种方式注册事件处理程序:java

  • HTML事件处理程序
  • DOM0级事件处理程序
  • DOM2级事件处理程序

 001:HTML事件处理程序chrome

就是说给html标签的属性设置事件处理程序;例如:浏览器

<p onclick="alert('hello')">点我</p>

p标签的属性onclick,把它的值设置成javascript代码字符串;这就是早期的js的用法app

如今这个方式,用的很少了,是由于HTML与JavaScript代码耦合太紧密。就是说html代码里有javascript代码,如今都讲究行为,样式,结构分离;ide

还有就是这里的javascript代码字符串中的this,event对象是能够直接使用的。例如:函数

<p onclick="console.log(this);console.log(event)">点我</p>

打印是这样:this

这是由于当指定一串javascript代码做为HTML事件处理程序属性值时,浏览器会把代码字符串为相似下面的函数中运行:url

function (event) {
    with(document) {
        with(this.form || {}) {
            with(this) {
                //这里是代码字符串
            }
        }
    }
}

这就解释了为何能直接使用event对象和this对象了。

可是还要注意有时咱们也这样用

<body>
<p onclick="aa();">点我</p>
<script type="text/javascript">
function aa() {
    console.log(this);
    console.log(event);
}
</script>
</body>

这样打印什么呢?

这时候的this就是window对象,这就是this对象有的时候让人很难肯定到底指的那个做用域。这这里的函数就是window调用的;还有就是若是你想引用指向元素的做用域的this,你能够向这个函数把这个this对象传递当参数过去,就像这样:

<body>
<p onclick="aa(this)">点我</p>
<script type="text/javascript">
function aa(_this) {
    console.log(_this);
    console.log(event);
}
</script>
</body>
View Code

打印:

002:DOM0级事件处理程序

  就是说,首先获取对这个元素DOM对象的引用,用DOM的getElementById()等这种方式获取到对这个元素对象的引用,而后就是每一个事件都在这个对象上用相应的属性,例如click事件,那么这个对象就有一个onclick属性与之对应,那你在这个对象的属性上绑定事件处理程序,例obj.onclick = function() {//相应代码};那么当你在点击的时候就会触发事件了;

这种方式你们都太熟悉了我就不举例了。

这种方式的优势就是几乎全部浏览器都兼容这种方式,通常不存在兼容性问题,咱们平时写代码如今也用的不少。简单方便嘛。

可是他也是有缺点的。每一个事件元素目标对于每一个事件类型只能最多注册一个事件处理程序。

例如:

obj.onclick = function () {
    //这里是代码1
};
obj.onclick = function () {
//这里是代码2
}

那么后面的会覆盖前面的,前面这个注册程序就不会执行了。

这种事件处理的程序在事件流中只能会冒泡;以前的在事件流说过这个;

要是想删除这个事件处理程序,就这样:

obj.onclick = null;

 003:DOM2级事件处理程序

DOM2级事件定义了两个方法,addEventListener()方法和removeEventListener()方法来处理和删除事件处理程序。它们能够接收三个参数,第一个参数:要处理的事件名,是一个字符串,可是要记得不要加“on”做为前缀,第二个参数:做为事件处理的函数,第三个参数:一个布尔值,这个布尔值为true时,那就在事件捕获阶段调用事件处理程序,若是是false那就在冒泡阶段调用事件处理程序。ps。这两个方法支持除IE8及如下的其余版本的全部浏览器

它的主要优势是能够为同一个对象的同一个事件绑定多个事件处理程序。而且注册的多个事件是按顺序执行的;

上例子:

<p id="test">点我</p>
<script type="text/javascript">
var test = document.getElementById("test");
    test.addEventListener("click",function () {
        alert("first click");
    },false);
  
test.addEventListener("click",function () {
  alert("secend click");
  },false);
</script>

若是你想移除事件处理程序,你就须要用到removeEventListener()方法,它也接收三个参数,这三个参数要和你用addEventListener添加事件时的参数同样,必需要如出一辙;而且若是addEventListener()的第二个参数,若是是匿名函数,那么用removerEventListener()是删除不了的;而且它也就只能处理用addEventListener注册的事件,那么用DOM0级注册的事件是不能用它删除的。

上离子:

test.addEventListener("click",fn,false);
test.removeEventListener('click',fn,false);

这样就跟你没有注册事件似的;

可是若是你这样:

test.addEventListener("click",fn,false);
test.addEventListener("click",fn,false);
test.addEventListener("click",fn,false);

却只会弹出一个alert,而不是三个,这就是若是你使用相同的参数在同一对象调用屡次,处理程序只是注册一次;

 IE永远都是一朵奇葩,IE8及如下不支持,可是有两个跟DOM2级的方法类似的事件处理方法,attachEvent()和detachEvent()方法。须要两个参数,第一参数:事件名,注意要在事件名前加“on”,第二个参数:事件处理程序函数;它也是能够绑定多个事件处理程序的;

这两个方法支持IE5 ——IE10,IE11就再也不支持了;

我就说说他和标准DOM2级的不一样,相同点就不提了,

  1.事件处理的做用域:

    不论是DOM0级仍是DOM2级他们的事件处理程序都是在它们所属元素的的做用域中运行,可是attachEvent却不是,事件处理程序会在全局做用域中运行,即事件处理程序中的this === window的,必定要记住这里面的this是指向window的

  2.当调用多个事件处理程序时:

    第一点:当为同一DOM对象同一个事件添加多个不一样的事件处理程序函数时:在IE5-IE8,这个调用顺序也很奇葩,后注册的函数,先被调用,可是IE9,IE10这个顺序就变过来了。

    第二点:当为同一个DOM对象的同一个事件添加多个相同的事件处理程序函数时:在IE5——IE8是你添加几个就执行几个,可是在IE9,10却不是这样,它只会为你注册一个事件处理程序,即你添加多个执行一个;ps。可是你若是用匿名函数,其实每一个匿名函数都是不一样的函数。即便你里面的内容同样。

因为IE的这种奇葩,咱们想用DOM2级的方法,可是又要照顾IE8及如下,这就产生了一个跨浏览器的事件处理程序

 

//经过能力检测来肯定浏览器支持
var EventUtil = {
    //param ele 元素对象
    //param type 事件类型
    //param handler 事件处理程序函数
    addHandler: function (ele,type,handler) {
        if(ele.addEventListener) {
            ele.addEventListener(type,handler,false);
        } else if (ele.attachEvent) {
            ele.attachEvent("on" + type,handler);
        } else {
            ele["on" + type] = handler;
        }
    },

    removeHandler: function (ele,type,handler) {
        if (ele.removeEventListener) {
            ele.removeEventListener(type,handler,false);
        } else if(ele.attachEvent) {
            ele.detachEvent("on" + type,handler);
        } else {
            ele["on" + type] = null;
        }
    }
}
跨浏览器事件处理程序

这个程序没有考虑IE的attachEvent()函数的做用域问题,也就是说它里面this不能用。但你能够直接引用这个对象,或者用event对象的srcElement获取到这个对象;

0x01 事件对象

在触发DOM上的事件时就会自动产生一个事件对象,这个对象包含这个事件的相关信息。

  001.获取event

就是直接在事件处理程序函数传递第一个参数就是event对象,这个是浏览器自动传递的。可是我今天亲测了一下发现:

 

 

 

 

     DOM0

DOM2级(addEventListener方法)

attachEvent

(仅IE5IE10支持)

chrome

支持传参;

也支持window.event

支持传参;

也支持window.event

 

 

IE

支持传参;

也支持window.event

(可是IE8及如下不支持传参方式)

支持传参;

也支持window.event

IE9-IE11支持下)

 

支持传参;

也支持window.event

firefox

仅支持传参;

 

仅支持传参;

 

 

 

opera

支持传参;

也支持window.event

支持传参;

也支持window.event

 

 

我用的浏览器都是最新的;

可是通常为了兼容性通常在用到的是时候这样写:

event = event || window.event;

002.取消默认操做行为

好比a标签只要你点击就跳转到href属性值的url,要是你不想让它跳转,你就要阻止默认行为;

DOM0级事件处理程序中的取消默认事件:方式1:在事件处理程序的函数中返回值设置为false,这个全部浏览器都支持;

                   方式2:event对象的方法,这样用:event.preventDefault()方法,可是这个只是一部分浏览器支持:chrome,opera,IE11;那就是说其余的都不支持了;还有IE自家的returnValue属性,event.returnValue = false;也可取消默认行为,仅IE5-IE10支持;

总结:若是你想用,那你就用返回值这种方式,兼容性最好了。

DOM2级中:那就直接用event.preventDefault();可是IE的attachEvent中要取消默认行为,要用event.returnValue = false;

003.阻止事件传播(冒泡或捕获)

DOM0级和DOM2级均可以用event对象的stopPropagation(),可是IE8及如下不支持;

IE8及如下能够用事件对象的cancelBubble属性,设置为true就取消冒泡;

004.在介绍一个event对象的一个type属性的用法:它指的是事件目标

在例子中说明:

function handler (evt) {
    switch(evt.type) {
        case "click": 
        //相应代码
         console.log("clicked");
        break;
        case "mouseover":
        // 相应代码
        console.log("mouseover");
        break;
        case "mouseout":
        //相应代码
        console.log("mouseout");
        break;
    }
}
test.onclick = handler;
test.onmouseover = handler;
test.onmouseout = handler;
View Code

多了不解释;

005.event中的属性

不一样的事件它的event对象所包含的属性也会有所不一样。

下列只是列出了每一个事件都会有的

属性/方法 类型 读/写 说明
bubbles Boolean read 代表事件是否冒泡
cancelable Boolean read 代表是否能够取消事件的默认行为
currentTarget Element read 其事件处理程序当前正在处理事件的那个元素
defaultPrevented Boolean read 为true表示已经调用了preventDafult()
detail Integer read 与事件相关的细节信息
eventPhase Integer read

代表调用事件处理程序的阶段:1表示捕获阶段

2表示处于目标,3表示冒泡阶段

preventDefault() Function read 取消事件的默认行为。若是cancelable是true,则可使用这个方法
stopImmediatePropagation() Function read 取消事件的进一步冒泡或捕获,同时阻止任何事件处理程序被调用
stopPropagation() Function read 取消事件的进一步捕获或冒泡
target Element read 事件目标
trusted Boolean read 为true表示事件是浏览器生成的,false表示是由开发人员生成的
type String read 被触发的事件类型
view AbstractView read 与事件相关的抽象视图

其实还有不少,好比鼠标事件还要有坐标位置信息,如clientX,clientY,screenX,screenY等,可是在键盘事件中就没有坐标信息

IE中所共有的

属性/方法 类型 读写 说明
cancelBubble Boolean read,write 默认为false,可是将其设置为true就取消事件的冒泡,(与DOM中的stopPropagation对应
returnValue Boolean read,write 默认为true,设置为false取消事件的默认行为(与DOM的preventDefault)
srcElement Element read 事件目标(与DOM中的target对应)
type String read 被触发的事件类型

 

 006.跨浏览器事件对象

 

var EventUtil = {
    getEvent:function (event) {
        return event ? event : window.event;
    },
    getTarget: function (event) {
        return event.target || event.srcElement;
    },

    preventDefault: function (event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },
    stopPropagation: function (event) {
        if(event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    }
};
View Code

 

 若有不许或错误,欢迎指正!

参考:javascript高级程序设计;

   javasript权威指南;

相关文章
相关标签/搜索