事件处理函数
- 绑定事件 = 绑定事件的处理函数(事件本身是存在的,绑定的是相应的反馈)
- 事件 + 事件的反馈 = 前端交互 (前端核心)
绑定事件的方式
1. 句柄绑定
- 默认(只能)是事件冒泡这种事件流
- 为某一个元素(事件源)指定了一个事件句柄(onclick,事件发生时要进行的操作)
oDiv.onclick = function(){} // 事件句柄 = 处理函数
- onclick绑定的事件处理函数内写的其他函数,在非严格模式下,指向的是window
- 【该方式】一个元素、同一事件、只能绑定一个事件处理函数(绑定多个取最后)
2. 内联事件监听器
在html上绑定,绑定执行(不建议使用,结构和逻辑应当分离),这种按属性绑定的方式优先级更低,会被js覆盖
3. 事件监听器
1) W3C规范,但IE9以下不支持
- 注册事件监听器/绑定事件监听器
- 可以绑定多个事件处理函数,都能执行;如果绑定了多次同一事件处理函数,只会执行一次
- 注意:事件类型没有加
on
elem.addEventListener(事件类型,事件处理函数,false);//false事件冒泡 true事件捕获
// 2种都执行
oBtn.addEventListener('click',function(){this.innerHTML = '加载中..'
},false)
oBtn.addEventListener('click',function(){console.log('加载更多事件')
},false)
oBtn.addEventListener('click',test,false);
oBtn.addEventListener('click',test,false);
function test(){console.log(1); // 打印1次
}
2)IE8及以下绑定方法
elem.attachEvent(事件类型,事件处理函数);
- 注意:事件类型加
on
点击事件 + IIFE
- 在绑定时,console.log(i)并没有执行,i没有保存,绑定的函数在for循环结束后被执行(点击了),访问到的是5
var oLi = document.getElementsByTagName('li'),len = oLi.length,item;
for (var i = 0; i < len; i++) {(function (j) {item = oLi[i];item.addEventListener('click', function () {console.log(i);}, false);}(i))
}
3) 事件处理程序的运行环境 / this
- 谁调用this就指向谁(attachEven是个特例,this指向window)
4) 【兼容】封装绑定事件处理函数
function addEvent(el, type, fn) {if (el.addEventListener) {el.addEventListener(type, fn, false);} else if (el.attachEvent) {el.attachEvent('on' + type, function () {fn.call(el);})} else {el['on' + type] = fn}
}
5)解除事件处理程序
// 句柄
element.onclick=null/false;// W3C规范事件监听器 (add时怎么写remove就得怎么写)
element.addEventListener('click',test,false);
element.removeEventListener('click',test,false)// IE8及以下事件监听器
element.detachEvent('onclick',test);
- 非严格模式下可以使用方法4
function removeEvent(elem, type, fn) {if (elem.addEventListener) {elem.removeEventListener(type, fn, false)} else if (elem.attachEvent) {elem.detachEvent('on' + type, fn)} else {elem['on' + type] = null}
}
标签嵌套
- 内联元素写嵌套关系,dom解析出来依然不是嵌套的
- a的特殊现象,变成block依然不能嵌套
事件冒泡与捕获
- dom结构中/嵌套结构中,从内到外,从下到上,事件从子元素一层一层向上传递的现象是事件冒泡
- 需绑定相同事件,向上传递时,父级有相同事件则触发
- 关心的是事件,而非事件处理函数
- 事件捕获则顺序相反,点击父元素,一直捕获到事件源,
事件监听器true
- 注意:dom结构嵌套,视觉上并不一定嵌套
- 点击黄色:事件捕获先于事件冒泡执行
- 点击红色,红色是事件源,事件源是按绑定顺序先后执行的,非冒泡非捕获
focus、blur、change、submit、reset、select
这些是没有捕获和冒泡事件的- IE浏览器是没有事件捕获的,除了Chrome以外的老版本浏览器都没有捕获,新版的浏览器(火狐、欧朋)有捕获的,主要和webkit blink内核有关系
取消冒泡
1. e.stopPropagation() (W3C)
2. e.cancelBuble = true (IE)
- attach的怎么取消
3. 【兼容】封装
function cacelBubble(e) {var e = e || window.event;if (e.stopPropagation) {e.stopPropagation();} else {e.cancelBubble = true;}
}
取消默认事件
1. 阻止右键菜单弹出
1)阻止右键菜单弹出
2)W3C:e.preventDefault()(IE9不兼容)
3)e.returnValue = false
function preventDefaultEvent(e) {var e = e || window.event;if (e.preventDefault) {e.preventDefault()} else {e.returnValue = false}
}
2. a标签默认事件
- 跳转和刷新页面
// 1)void(0)相当于return 0
<a href = "javascript:void(0)">百度一下</a>
// 2)
<a href = "javascript:;">百度一下</a>
// 3)锚点方式
<a href = "#">百度一下</a>
// 4)
a.onclick = function(e){e.preventDefault();
}
举例