冒泡
事件流
定义:
事件传播的方式。从document一层层向内捕获到目标元素再一层层向外冒泡。浏览器一般都在冒泡阶段处理事件[IE浏览器不认识捕获,但是捕获客观存在]
捕获阶段->目标阶段->冒泡阶段
阻止冒泡
if(e.stopPropagation){
e.stopPropagation();//非ie浏览器
}else{
e.cancelBubble=true;//兼容ie浏览器
}
事件监听
特点:
1)可以指定事件在哪个阶段触犯(捕获阶段、冒泡阶段)
2)可以添加多个同类型的监听,谁在前谁就先触发
添加事件监听
/**
* 后面的参数均参照以下的名字
* @param obj <DOM object>添加事件监听的DOM对象
* @param type <string> 事件句柄(非IE浏览器不带"on")
* @param fn < function> 事件处理函数
* @param isCapture <Boolean>是否捕获(false:冒泡阶段,true:捕获阶段,默认为false)
*
*/
//非IE浏览器
obj.addEventListener(type,fn,isCapture);
//IE浏览器
obj.attachEvent(type,fn);
移除监听事件
//非IE浏览器
obj.removeEventListener(type,fn);
//IE浏览器
obj.edtachEvent(type,fn);
注意:如果isCapture未传参则它的值为undefined
if(isCapture===undefined){
isCapture=false;
}
小结:
事件绑定和事件监听的区别:
1)事件绑定只可以在冒泡阶段进行,而且一个对象可以绑定一个事件。
2)事件监听可以指定在捕获阶段和冒泡阶段进行,取决于isCapture的传值,而且事件监听可以添加多个事件。
3)事件绑定取消事件是对事件重新赋值(例如赋null值)。
4)事件监听有专门的移除事件方法。(obj.removeEventListener(type,fn)或者obj.detachEvent(type,fn))
重点案例:
点击li弹出对应的下标
错误示范
var list=document.querySelectorAll('li');//获取标签名为li的伪数组
for(var i=0;i<list.length;i++){
list[i].onclick=function(){
console.log(i);//i=4
}
}
改正方法
//方法1:通过自定义属性编号
var list=document.querySelectorAll('li');//获取标签名为li的伪数组
for(var i=0;i<list.length;i++){
list[i].index=i;
list[i].onclick=function(){
console.log(this.index);
}
}
//方法2:通过Array.form(list)把可迭代的集合变为数组
//每次循环都有4个函数,每个i只属于每个函数内部,互不影响
var list=document.querySelectorAll('li');//获取标签名为li的伪数组
Array.from(list).forEach(function(li,i)){
//li:参数里的每一项
//i:下标
li.onclick=function(){
console.log(i)
}
}
//方法3:利用let声明一个块级变量
//每一趟for循环进入一个新的块级,所以每次点击的都是li内部的i,不会互相影响
for(let i=0;i<list.length;i++){
list[i].onclick=function(){
console.log(i)
}
}
案例小结:
1)绑定事件用for循环时,for循环在页面加载时就全部运行完了
2)循环只负责绑事件,事件的触发在循环结束以后,i已经加到length了