JS事件
- 事件绑定方式
- 事件对象
- 事件传播流
- 事件代理
一、事件绑定方式
方式一:通过HTML标签行间属性内绑定
<button onclick="fn1(this)">点击</button>
<script>
function fn1(el){
alert("111")
//弹出的是
//删除方式:setAttribute() 给要删除的事件为空
el.setAttribute('onclick','')
}
</script>
- 优点:结构简单,代码简洁
- 缺点:1、写在行间的,不方便维护
2、绑定的事件处理函数,只能写在全局变量里,写在局部变量里变量名会污染。
3、通过传参才能获取到this,因为直接获取就拿到的是window
4、无法追加事件
- 应用的场景:结构单一,业务单一,不用考虑变量名污染的场景
方式二:通过DOM元素节点绑定
<button id="btn">点击</button>
<button id="btn1">点击二</button>
<script>
(function(){
btn.onclick = function(){
alert("被点击了")
}
btn.onclick = function(){
alert("111")
}
//那这个弹出来的就是111,因为会覆盖掉前面的
//不是一个全局变量,不受作用域限制,还可以形成闭包
//动态绑定事件
var oDiv = document.createElement('div');
oDiv.onclick = function(){
alert("111")
}
})
//删除事件
(function(){
btn1.onclick = function(){
this.innerHTML = "点击过";
this.onclick = null;
}
})()
</script>
-
优点:1、HTML与JS分开方便维护
2、分割作用域,防止变量名污染
3、不需要传参,内部的this可以直接获取到节点对象
-
缺点:不能实现多个事件处理函数的绑定,因为后面绑定的事件会覆盖前面的,
如果实现多个事件处理函数绑定,代码会比较冗长,结构也很复杂。
-
应用场景:主要用在任何需要绑定事件的场景。
方式三:通过侦听器绑定
<button id="btn">点击</button>
<script>
//一个事件侦听器 事件处理函数 在事件的什么阶段
btn.addEventListener('click',function(){},true);
btn.addEventListener('click',function(){},true);
//如果三个参数都相同那么只执行第一个行代码,后面的相同代码会被忽略。
//两个侦听绑定函数之间传参
btn.addEventListener('click',function(){
alert('被点击了');
var name = '张三';
this.name = name;//给btn按钮添加name属性
})
btn.addEventListener('click',function(){
this.innerHTML = this.name;//将btn name属性的值拿出来。放到按钮中
})
</script>
-
优点: 1、JS HTML分离
-
2、不受作用域限制
-
3、内部this指向调用对象
-
4、可以动态添加、动态删除事件处理函数
-
-
缺点:IE8及以下不支持,需要编写兼容代码,
-
el.addEventListener('事件类型',事件处理函数也可以放对象,事件传播控制)
-
参数1 : 事件类型,不带'on'
-
参数2 : 可以是命名函数,也可以匿名函数,可以是一个用handleEvent函数的对象
-
参数3 : 用来控制事件的传播方向,默认是false
-
通过addEventListener绑定多个事件时,执行顺序与绑定顺序保持一致
-
通过addEventListener多次绑定相同的事件,相同事件:必须三个参数都一致
-
通过addEventListener绑定多个事件时,三个参数中有一个参数不一样时
就是新创建了一个侦听器。
-
删除侦听事件处理函数时,removeEventListener('事件类型,函数名,true)
三个参数必须要给定,匿名函数绑定的侦听器不能被删除。如果要能删除,
那就要用命名函数进行绑定
四、事件侦听器兼容
-
IE9以上写法
el.addEventListener('click',fn(),true)
-
IE8及以下写法
detachEvent('onclick',fn)//必须要加on
-
兼容写法
<button id="btn1">点击</button> <script> // 侦听谁 侦听的事件类型 事件处理函数 function bindEvent(el,type,callback){ if(el.addEventListener){ //IE8以上其他非IE浏览器 el.addEventListener(type,callback) }else{ //IE8及以下 el.attachEvent('on' + type,callback) } } //删除事件 // 侦听谁 侦听的事件类型 事件处理函数 function removeEvent(el,type,callback){ if(el.removeEventListener){ //非IE8以下 el.removeEventListener(type,callback) }else{ //IE8及以下 // el.datachEvent('on' +type,callback) } } bindEvent(btn1,'click',function(){//这是个匿名函数 alert("按钮被点击了") }) //给btn1绑定点击事件点击时执行fn函数 bindEvent(btn1, 'click',fn); //三个参数必须要给定,匿名函数绑定的侦听器不能被删除。如果要能删除,那就要用命名函数 removeEvent(btn1, 'click', fn); function fn(){ alert("被调用了") } btn1.attachEvent('onclick',fn) //它这里面必须要带On不带是不行的 btn2.attachEvent('onclick',fn) //那么在IE上面就是后面的btn2先执行 </script>
-
IE8使用attachEvent绑定事件和addEventListener的区别
-
1、attachEvent只能写两个参数,addEventListener可以写三个参数,
第三个参数的默认值为false
-
2、attachEvent注册事件与事件的处理函数的执行顺序相反,先注册的后执行
-
attachEvent只支持冒泡阶段
-
3、attachEvent注册的事件处理函数内部,this内部是拿不到的,总是指向window
-
五、事件传播流
<div class="box1">
<div class="box2">
<div class="box3"></div>
</div>
</div>
<script>
var oBox1 = document.querySelector('.box1');
var oBox2 = document.querySelector('.box2');
var oBox3 = document.querySelector('.box3');
oBox1.addEventListener('click',function(){
alert('box1');
},true)
oBox2.addEventListener('click',function(){
alert('box2');
},true)
oBox3.addEventListener('click',function(){
alert('box3');
},true)
事件的传播流:
-
1、浏览器在无时无刻都在发生事件流和是否绑定了事件处理函数无关
-
2、事件流分为三个阶段
-
阶段一、事件捕获阶段
从根节点document一层一层往下找,找到目标节点以后,去进行捕获
-
阶段二、事件目标阶段
找到目标节点以后,看是不是绑定了事件处理函数
-
阶段三、事件的传播阶段(事件冒泡阶段)
目标阶段结束后,将该类型事件向上一层一层往回传播。每层都会判断是否绑定了
这种类型事件的处理函数,如果绑定了就调用 -
事件流引发的两个编码问题
-
1、阻止事件冒泡:父子级嵌套情况下,都绑定了相同类型的事件处理函数,
为了保证各自执行各自的需要阻止事件冒泡
e.stopPropagation()//阻止冒泡
- 2、事件代理:利用事件冒泡,可以将子级的事件处理函数,绑定在父级的同级类型事件处理函数内
六、事件对象
事件对象:在用户触发事件时。传入事件对象,会向事件处理函数传递一个对象数据,该对象数据就称为事件对象。
-
基本获取方法
btn.onclick = function(e){ console.log('我拿到e(事件对象)了') }
-
ie8写法
btn.onclick = function(e){ //IE8不支持在事件调用时,传入事件对象,但是有一个全局变量event会被赋值成对应的事件对象。 console.log(window.event) console.log('我拿到e(事件对象)了') }
-
兼容写法
<body> <button id='btn1'>点击</button> <button id='btn2'>点击二</button> <button onclick='fn(event)'>点击三</button> </body> <script> btn1.onclick = function(e){ //e event evt 可能的名称 e = e || window.event; //兼容IE8 //IE8不支持事件调用时,传入事件对象, 但是有一个全局变量 event会被赋值成对应的事件对象,因此需要写兼容 console.log(e);//能拿到 } btn2.addEventListener('click',function(e){ console.log(e);//能拿到 }) function fn(e){ console.log(e);//能拿到 } </script>
七、阻止冒泡事件
1.阻止向上传递冒泡事件
-
非ie8写法
e.stopPropagation();
-
ie8写法(目前谷歌等其他浏览器也能使用)
e.cancelBubble = true;
-
兼容写法
// 阻止事件冒泡
if(e.stopPropagation){
e.stopPropagation(); //非ie8
}else{
e.cancelBubble = true;//ie8
}
2.阻止当前节点其他事件
- DOM3定义事件冒泡阻止方法,可以处理阻止事件传播以外,还可以阻止当前节点其他事件
e.stopImmediatePropagation();
- 示例代码
<body>
<div id="box1">
<div id="box2"></div>
</div>
<div id="box3">
<div id="box4"></div>
</div>
</body>
<script>
box1.onclick = function(){
alert('box1');
}
box2.onclick = function(e){
//兼容ie写法
e = e || window.event;
// 阻止事件冒泡
if(e.stopPropagation){
e.stopPropagation(); //非ie8
}else{
e.cancelBubble = true;//ie8
}
// e.stopPropagation();
alert('box2');
}
box3.addEventListener('click',function(){
alert("box3")
})
//给box4添加两个事件,因为 e.stopImmediatePropagation(),只会出现当前事件
box4.addEventListener('click',function(e){
e = e || window.event;
// 阻止事件传播,还可以阻止当前节点其他事件
e.stopImmediatePropagation();
alert("box4")
})
box4.addEventListener('click',function(){
alert("box44")
})
</script>
八、阻止系统默认事件
-
非ie8写法
e.preventDefault()
-
ie8写法
e.returnValue = false
-
兼容写法
if(e.preventDefault){ e.preventDefault();//非ie8写法 }else{ e.returnValue = false; //ie8写法 }
-
只能给标签绑定点击事件的时候使用(node.ontype )
return false;
- 侦听器绑定事件示例
bindEvent(b,'click',function(e){ //事件传播流兼容 e = e || window.event if(e.preventDefault){ e.preventDefault(); //非ie8 }else{ e.returnValue = false; //ie8 其他高级非ie8浏览器 } }) //处理侦听器绑定事件兼容 function bindEvent(el, type, callback) { if (el.addEventListener) { //IE9以上, 其他非IE浏览器 el.addEventListener(type, callback) } else { // IE8 及以下 el.attachEvent('on' + type, callback) } }
- 行间阻止系统默认事件
function fn(e){ if(e.preventDefault){ e.preventDefault(); }else{ e.returnValue = false; } console.log(11111); }
- 标签对象绑定事件阻止系统默认事件
a.onclick = function(e){ e = e || window.event console.log("1111"); return false; //只能标签对象绑定事件能够使用 }
九、事件代理
将事件绑定在父级标签上,通过e.target(触发事件的目标对象)获得当前点击的按钮,采用给父级标签添加属性,属性中绑定函数的方法,进行事件绑定。
box.addEventListener('click',function(e){
// e.target : 触发事件的目标对象
this[e.target.className](e.target)
})
box.box1 = function(el){
console.log(el);
}
box.box2 = function(el){
console.log(el);
}
网友评论