JavaScript绑定事件的三种方式

@(javascript)[JavaScript事件绑定]javascript

JavaScript绑定事件的三种方式

  • 使用内联
  • 使用.onclick的方式
  • 使用事件监听addEventListener的方式

内联

形式:html

<input type="button" value="按钮" onclick="alert(1);">
复制代码

这种方式就是在一个元素上面直接绑定了一个点击onclick事件,此事件为DOM 0级标准。同时,这个事件的优先级是最高的。java

使用对象.事件的形式

形式node

<input type="button" value="按钮">

<script type="text/javascript"> var bt = document.getElementsBytagname("input")[0]; bt.onclick = function(){ alert(2) } </script>
复制代码

使用这种形式也是能够给一个DOM元素添加上一个事件。这个也是DOM 0级标准闭包

以上的弊端

以上两种方式都是存在一个弊端的,就是一个元素只能添加一个事件。第一种就不用说了,写在行内就一个属性。至于第二种,有的网友可能会说我能够再写一个,好比:函数

<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,只会吧前面的给覆盖了。因此这样的写法也只能添加一个事件。ui

那么,问题来了。我要给一个元素(DOM对象)添加两个甚至是多个事件,使用什么呢?此时,就须要使用addEventListener的方式来添加事件。this

addEventListener

形式:spa

<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官网的一个话 代理

三个参数:

  1. 事件类型,不须要添加上on
  2. 事件函数
  3. 是否捕获(布尔值),默认是false,即不捕获,那就是冒泡。

那么捕获和冒泡又是什么呢? 这是三个盒子,相互嵌套的关系

<div id="a">
	a
	<div id="b">
		b
		<div id="c">c</div>
	</div>
</div>
复制代码

那么捕获是什么意思呢?

弓箭射过来,没穿过一个盒子,就捕获一次,这个过程就是捕获过程。 而下面的就是冒泡

捕获和冒泡会影响到事件的执行顺序

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。先执行的捕获在是冒泡。得出:同时存在捕获与冒泡时,捕获的优先级是高于冒泡的

下面,咱们变一下代码:

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

再来:

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的冒泡放在这里来了
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

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的标准事件相比,主要是如下三点不一样:

  1. 绑定事件的函数不一样,IE中使用attachEvent()和detachEvent()
  2. 事件必须加上on
  3. IE6模型中,不支持捕获,只支持冒泡
  4. IE中还有毛病,先绑定的事件后发生(准确的说是随机发生)
  5. IE中this指向window

更新与2017年12月2日14:30:05

关于使用addEventListener

给元素添加事件通常使用addEventListener的方式来添加,这样才能够个一个元素添加多个事件。可是因为addEventListener单词太长,容易写错,而且代码压缩的时候不会压缩,因此通常不多直接使用他,而是使用函数把他封装起来使用,避免出错:

function addEvent(ele,type,fn){
	ele.addEventListener(type,function(e){
		fn(e)
	})
}
复制代码

使用以上的方式能够减小出错率以及方便

关于事件代理(委托)

通常状况下,若是一个元素下存在多个点击事件,代码结构以下:

<ul id="box">
	<li>list-1</li>
	<li>list-2</li>
	<li>list-3</li>
	<li>list-4</li>
</ul>
复制代码

此时,若是你要给每个li标签添加一个点击事件,弹出每个li的索引值,初学者可能会使用for循环的方式来添加:

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)
	})
}
复制代码

或者是使用闭包:

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的个数可能发生改变,若是是这样的话,可能会出一些问题。那么,此时若是使用事件代理的方式,效果会更好。 事件代理代码:

var oBox = document.getElementById("box");

addEvent(oBox,'click',function(e){
	var target = e.target;
	// 判断点击的是li
	if ( target.nodeName == 'LI' ) {
		alert(target.innerHTML)
	}
})
复制代码

这样也是能够的,不过此时的addEvent函数点击的时候就须要在fn里面判断点击的是哪个标签。为了更好的使用addEvent,咱们能够改进一下:

function addEvent(ele,type,selector,fn){
	// 若是只有三个参数,那么3,4互换
	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(e)
		}
	})
}
复制代码

这时点击li弹出innerHTML就能够这样实现

addEvent(oBox,'click','li',function(e){
	alert(this.innerHTML)
})
复制代码
相关文章
相关标签/搜索