如何绑定事件
- ele.onxxx = function (event) {}
兼容性很好,但是一个元素只能绑定一个处理程序
基本等同于写在HTML行间上 - obj.addEventListener(type, fn, false);
IE9以下不兼容,可以为一个事件绑定多个处理程序 - obj.attachEvent(‘on’ + type, fn);
IE独有,一个事件同样可以绑定多个处理程序
addEventListener的用法
<div style="width:100px;height:100px;background-color: red;position:absolute;left:0;top:0;"></div>
<script>
// 句柄
var div = document.getElementsByTagName('div')[0];
div.addEventListener('click', function () {
console.log('a');
}, false);
div.addEventListener('click', function () {
console.log('b');
}, false);
div.addEventListener('click', test, false);
div.addEventListener('click', test, false);
div.addEventListener('click', test, false);
function test() {
console.log('绑定过后只会执行一次test函数');
// 而attachEvent绑定相同的函数可以多次执行,但是只有IE才有attachEvent
}
// div.onclick = function () {
// console.log('兼容好');
// }
</script>
ul闭包问题
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<ul>
<li>a</li>
<li>a</li>
<li>a</li>
<li>a</li>
</ul>
<script>
var liCol = document.getElementsByTagName('li'),
len = liCol.length;
for(var i = 0; i < len; i++) {
(function(i){
liCol[i].addEventListener('click', function () {console.log(i)}, false);
}(i));
}
</script>
</body>
</html>
事件处理程序的运行环境
- ele.onxxx = function (event) {}
程序this指向是dom元素本身 - obj.addEventListener(type, fn, false);
程序this指向是dom元素本身 - obj.attachEvent(‘on’ + type, fn);
程序this指向window
IE独有的attachEvent中this指向window的解决办法<div style="width:100px;height:100px;background-color: red;"></div> <script> var div = document.getElementsByTagName('div')[0]; // 因为IE独有的attachEvent它的this是指向window的, // 但是用起来的时候绝大部分都是想调用该元素, // 所以可以用下面这种形式来改变this指向 div.attachEvent('onclick', function () { handle.call(div); }); function handle() { } </script>
封装兼容性的 addEvent(elem, type, handle);方法
function addEvent(elem, type, handle) {
if(elem.addEventListener) {
elem.addEventListener(type, handle, false)
} else if(elem.attachEvent) {
elem.attachEvent('on' + type, function () {
handle.call(elem);
})
} else {
elem['on' + type] = handle;
}
}
解除事件处理程序
- ele.onclick = false/‘’/null;
- ele.removeEventListener(type, fn, false);
- ele.detachEvent(‘on’ + type, fn);
- 注:若绑定匿名函数,则无法解除
只会生效一次的点击方法
<div style="width:100px;height:100px;background-color: red;"></div>
<script>
var div = document.getElementsByTagName('div')[0];
div.onclick = function () {
console.log('a');
this.onclick = null;
}
</script>
事件处理模型 — 事件冒泡、捕获
-
事件冒泡
- 结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)
-
事件捕获
- 结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自底向上)
- IE没有捕获事件
-
触发顺序,先捕获,后冒泡
-
focus, blur, change, submit, reset, select 等事件不冒泡
事件冒泡demo(看控制台)
为什么说非视觉呢,你把注释的加上就明白了
如果想实现事件捕获的话,把addEventListener中的false都改成true即可
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
<style>
.wrapper{
width: 300px;
height: 300px;
background-color: red;
}
.content{
width: 200px;
height: 200px;
background-color: green;
/*margin-left: 300px;*/
}
.box{
width: 100px;
height: 100px;
background-color: orange;
/*margin-left: 200px;*/
}
</style>
</head>
<body>
<div class="wrapper">
<div class="content">
<div class="box"></div>
</div>
</div>
<script>
var wrapper = document.getElementsByClassName('wrapper')[0];
var content = document.getElementsByClassName('content')[0];
var box = document.getElementsByClassName('box')[0];
wrapper.addEventListener('click', function () {
console.log('wrapper');
}, false);
content.addEventListener('click', function () {
console.log('content');
}, false);
box.addEventListener('click', function () {
console.log('box');
}, false);
</script>
</body>
</html>
取消冒泡和阻止默认事件
- 取消冒泡:
- W3C标准 event.stopPropagation();但不支持ie9以下版本
- IE独有event.cancelBubble = true;(谷歌也实现了)
<!doctype html> <html lang="en"> <head> <title>Document</title> <style> .wrapper{ width: 300px; height: 300px; background-color: red; } </style> </head> <body> <div class="wrapper"></div> <script> document.onclick = function () { console.log('this is document') } var div = document.getElementsByClassName('wrapper')[0]; div.onclick = function (e) { // 取消冒泡时间 // e.stopPropagation(); e.cancelBubble = true; this.style.background = "green"; } </script> </body> </html>
- 封装取消冒泡的函数 stopBubble(event)
function stopBubble(event) { if(event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; }
``` - 阻止默认事件:
- 默认事件 — 表单提交,a标签跳转,右键菜单等
- 1.return false; 以对象属性的方式注册的事件才生效
例子:右键页面不会出现菜单document.oncontextmenu = function (){ return false; }
- 2.event.preventDefault(); W3C标准,IE9以下不兼容
document.oncontextmenu = function (e){ e.preventDefault(); }
- 3.event.returnValue = false; 兼容IE 封装阻止默认事件的函数 cancelHandler(event);
document.oncontextmenu = function (e){ e.returnValue = false; }
封装阻止默认事件的函数 cancelHandler(event);
function cancelHander(event){
if(event.preventDefault){
event.preventDefault();
} else {
event.returnValue = false;
}
}
取消a标签的默认事件
void()相当于函数中return false;
<a href="javascript:void(false)">demo</a>
事件对象
- event || window.event 用于IE
- 事件源对象:
- event.target 火狐只有这个
- event.srcElement le只有这个
- 这两chrome都有
- 兼容性写法
<!doctype html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
<script>
var ul = document.getElementsByTagName('ul')[0];
ul.onclick = function (e) {
var event = e || window.event;//兼容event
var target = event.target || event.srcElement;//兼容事件源对象
console.log(target.innerText);
}
</script>
</body>
</html>
事件委托
- 利用事件冒泡,和事件源对象进行处理
- 有点:
- 1.性能不需要循环所有的元素一个个绑定事件
- 2.灵活当有新的子元素时不需要重新绑定事件
事件分类
鼠标事件
- click、mousedown、mousemove、 mouseup、contextmenu、mouseover、mouseout、mouseenter、mouseleave
- 用button来区分鼠标的按键,0/1/2 (按下左键为0,滚动轮为1,右键为2)
- DOM3标准规定:click事件只能监听左键,只能通过mousedown和mouseup来判断鼠标键
- 如何解决mousedown和click的冲突
var firstTime = 0; var lastTime = 0; var key = false; // 鼠标按下时 document.onmousedown = function () { firstTime = new Date().getTime(); } // 鼠标抬起时 document.onmouseup = function () { lastTime = new Date().getTime(); // 时间小于300ms则触发点击事件 if(lastTime - firstTime < 300) { key = true; } } document.onclick = function () { if(key) { console.log('click'); key = false; } }
键盘事件
- keydown keyup keypress
- keydown > keypress > keyup
- keydown 和 keypress 的区别
- keydown 可以响应任意键盘按键(返回大小写区分不了),keypress只可以响应字符类键盘按键
- keypress返回ASCII码,可以转换成相应字符
事件分类
- 文本操作事件
- input, focus, blur, change
<!doctype html> <html lang="en"> <head> <title>Document</title> <style> input{ border:1px solid #01f; } </style> </head> <body> <input type="text" value="请输入用户名" style="color:#999" onfocus="if(this.value=='请输入用户名'){this.value='';this.style.color='#424242'}" onblur="if(this.value==''){this.value='请输入用户名';this.style.color='#999'}"> <script type="text/javascript"> var input = document.getElementsByTagName('input')[0]; input.oninput = function (e) { console.log(this.value); } </script> </body> </html>
- 窗体操作类(window上的事件)
- scroll load