使用内联
使用.onclick
的方式
使用事件监听addEventListener
的方式
内联 形式:
1 <input type ="button" value ="按钮" onclick ="alert(1);" >
这种方式就是在一个元素上面直接绑定了一个点击onclick
事件,此事件为DOM 0级标准 。同时,这个事件的优先级是最高的。
使用对象.事件的形式 形式
1 2 3 4 5 6 7 8 <input type ="button" value ="按钮" > <script type ="text/javascript" > var bt = document .getElementsBytagname("input" )[0 ]; bt.onclick = function ( ) { alert(2) } </script >
使用这种形式也是可以给一个DOM元素添加上一个事件。这个也是DOM 0级标准 。
以上的弊端 以上两种方式都是存在一个弊端的,就是一个元素只能添加一个事件。第一种就不用说了,写在行内就一个属性。至于第二种,有的网友可能会说我可以再写一个,比如:
1 2 3 4 5 6 7 8 9 10 11 12 <input type ="button" value ="按钮" > <script type ="text/javascript" > var bt = document .getElementsBytagname("input" )[0 ]; bt.onclick = function ( ) { alert(2) } bt.onclick = function ( ) { alert(3) } </script >
写是可以这么写。那么我们先来看一看这个写法的意思,这种写法的本质就是在一个对象上添加一个属性,就上面的例子,就是在bt
这个对象上添加一个onclick
属性。那么,如果在之后的代码中也存在bt.onclcik
,只会吧前面的给覆盖了。所以这样的写法也只能添加一个事件。
那么,问题来了。我要给一个元素(DOM对象)添加两个甚至是多个事件,使用什么呢?此时,就需要使用addEventListener
的方式来添加事件。
addEventListener 形式:
1 2 3 4 5 6 7 8 9 10 11 <input type ="button" value ="按钮" > <script type ="text/javascript" > var bt = document .getElementsBytagname("input" )[0 ]; bt.addEventListener("click" , function ( ) { alert(1) }) bt.addEventListener("click" , function ( ) { alert(2) }) </script >
上面的方式就可以给一个DOM对象绑定一个或者是多个事件。强烈推荐使用这一种绑定事件的方式 。 使用addEventListener
的方式还可以拥有第三个参数。 以下是W3C官网 的一个话
三个参数:
事件类型,不需要 添加上on
事件函数
是否捕获(布尔值),默认是false
,即不捕获,那就是冒泡。
那么捕获和冒泡又是什么呢? 下面来看一张图: 这是三个盒子,相互嵌套的关系
1 2 3 4 5 6 7 <div id ="a" > a <div id ="b" > b <div id ="c" > c</div > </div > </div >
那么捕获是什么意思呢? 弓箭射过来,没穿过一个盒子,就捕获一次,这个过程就是捕获过程。 而下面的就是冒泡
捕获和冒泡会影响到事件的执行顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 var a = document .getElementById("a" );var b = document .getElementById("b" );var c = document .getElementById("c" );a.addEventListener("click" , function ( ) { alert("b-a" ) },true ) b.addEventListener("click" , function ( ) { alert("b-b" ) },true ) c.addEventListener("click" , function ( ) { alert("b-c" ) },true ) a.addEventListener("click" , function ( ) { alert("m-a" ) },false ) b.addEventListener("click" , function ( ) { alert("m-b" ) },false ) c.addEventListener("click" , function ( ) { alert("m-c" ) },false )
上面的代码的执行顺序为:b-a,b-b,b-c,m-c,m-b,m-a。先执行的捕获在是冒泡。得出:同时存在捕获与冒泡时,捕获的优先级是高于冒泡的
下面,我们变一下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 var a = document .getElementById("a" );var b = document .getElementById("b" );var c = document .getElementById("c" );a.addEventListener("click" , function ( ) { alert("b-a" ) },true ) b.addEventListener("click" , function ( ) { alert("b-b" ) }) c.addEventListener("click" , function ( ) { alert("b-c" ) },true ) a.addEventListener("click" , function ( ) { alert("m-a" ) },false ) b.addEventListener("click" , function ( ) { alert("m-b" ) },false ) c.addEventListener("click" , function ( ) { alert("m-c" ) },false )
此时的执行顺序为:b-a,b-c,m-c,b-b,m-b,m-a
再来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 var a = document .getElementById("a" );var b = document .getElementById("b" );var c = document .getElementById("c" );a.addEventListener("click" , function ( ) { alert("b-a" ) },true ) b.addEventListener("click" , function ( ) { alert("m-b" ) },false ) b.addEventListener("click" , function ( ) { alert("b-b" ) }) c.addEventListener("click" , function ( ) { alert("b-c" ) },true ) a.addEventListener("click" , function ( ) { alert("m-a" ) },false ) c.addEventListener("click" , function ( ) { alert("m-c" ) },false )
此时的执行顺序为:b-a,b-c,m-c,m-b,b-b,m-a得出,没有捕获的时候谁在前面先执行谁
OK。事件绑定就此结束。下面说说取消事件绑定吧。如果要取消一个使用addEventListener
绑定的事件函数,使用removeEventListener
可以移除事件。 与添加事件一致。不过如果使用这个,最好把这个函数给单离拿出来。
停止传播 使用stopPropagation
可以阻止事件的传播 。不能使用return false
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 var a = document .getElementById("a" );var b = document .getElementById("b" );var c = document .getElementById("c" );a.addEventListener("click" , function ( ) { alert("b-a" ) },true ) b.addEventListener("click" , function ( ) { alert("b-b" ) }) c.addEventListener("click" , function ( ) { alert("b-c" ) },true ) a.addEventListener("click" , function ( ) { alert("m-a" ) }) b.addEventListener("click" , function ( ) { alert("m-b" ) },false ) c.addEventListener("click" , function (e ) { alert("m-c" ) e.stopPropagation(); },false )
此时的顺序:b-a,b-c,m-c。不会传递,后面的不会执行了。阻止捕获也是一样,添加之后就不会在继续往下传递了。
这里有涉及到一个阻止事件的默认行为 :preventDefault
或者是前面提到的return false
对于IE下的事件绑定 适用与IE6,7,8 IE的事件与模型与W3C的标准事件相比,主要是以下三点不同:
绑定事件的函数不同,IE中使用attachEvent()和detachEvent()
事件必须加上on
IE6模型中,不支持捕获,只支持冒泡
IE中还有毛病,先绑定的事件后发生(准确的说是随机发生)
IE中this
指向window
更新与2017年12月2日14:30:05 关于使用addEventListener
给元素添加事件一般使用addEventListener
的方式来添加,这样才可以个一个元素添加多个事件。但是由于addEventListener
单词太长,容易写错,并且代码压缩的时候不会压缩,所以一般很少直接使用他,而是使用函数把他封装起来使用,避免出错:
1 2 3 4 5 6 7 function addEvent (ele,type,fn ) { ele.addEventListener(type,function (e ) { fn.call(ele, e) }) }
使用以上的方式可以减少出错率以及方便
关于事件代理(委托) 一般情况下,如果一个元素下存在多个点击事件,代码结构如下:
1 2 3 4 5 6 <ul id ="box" > <li > list-1</li > <li > list-2</li > <li > list-3</li > <li > list-4</li > </ul >
此时,如果你要给每一个li
标签添加一个点击事件,弹出每一个li
的索引值,初学者可能会使用for
循环的方式来添加:
1 2 3 4 5 6 7 8 var oLis = document .getElementsByTagName("li" );for (var i = 0 ; i < oLis.length; i++) { oLis[i].i = i; addEvent(oLis[i],"click" ,function (e ) { alert(this .i) }) }
或者是使用闭包:
1 2 3 4 5 6 7 8 9 var oLis = document .getElementsByTagName("li" );for (var i = 0 ; i < oLis.length; i++) { (function (i ) { addEvent(oLis[i],"click" ,function (e ) { alert(i) }) })(i) }
但是以上两种都不是一个最好的方法,因为你的li
的个数可能发生改变,如果是这样的话,可能会出一些问题。那么,此时如果使用事件代理的方式,效果会更好。 事件代理代码:
1 2 3 4 5 6 7 8 9 var oBox = document .getElementById("box" );addEvent(oBox,'click' ,function (e ) { var target = e.target; if ( target.nodeName == 'LI' ) { alert(target.innerHTML) } })
这样也是可以的,不过此时的addEvent
函数点击的时候就需要在fn
里面判断点击的是哪一个标签。为了更好的使用addEvent
,我们可以改进一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function addEvent (ele,type,selector,fn ) { if ( fn == null ) { fn = selector; selector = null } ele.addEventListener(type,function (e ) { var target; if ( selector ) { target = e.target; if (target.matches(selector)){ fn.call(target, e) } } else { fn.call(ele, e) } }) }
这时点击li
弹出innerHTML就可以这样实现
1 2 3 addEvent(oBox,'click' ,'li' ,function (e ) { alert(this .innerHTML) })