事件
绑定事件处理函数
- ele.onxxx = function(event){}
<div onclick="console.log('a')"></div>
var div = document.getElenmentsByTagName('div')[0];
div.onclick = function(){
this.style.backgroundColor = 'green';
}
兼容性很好,但是一个元素的同一个事件上只能绑定一个处理程序 基本等同于写在HTML行间
- obj.addEventListener(type,fn,false) 事件类型,处理函数 false
var div = document.getElenmentsByTagName('div')[0];
div.addEventListener('click',text,false);
div.addEbentListener('click',text2,false);
function text(){
console.log('a');
}
function text2(){
console.log('b');
}
w3c标准 可以为一个事件绑定多个处理程序
- obj.attachEvent(‘onxxx’,fn)
div.attachEvent('onclick',function(){
console.log('IE');
})
IE独有,一个事件同样可以绑定多个处理程序
- 监听事件 for循环闭包问题
let liCol = document.getElenmentsByTagName('li'),
len = liCol.length;
for(let i = 0;i<len;i++){
(function(i){
loCol[i].addEventListener('click',function(){
console.log(i); //此处形成闭包
},false);
}(i))
}
事件处理程序的运行环境
- ele.onxxx = function(event){}
程序 this 指向是dom元素本身
- obj.addEbentListener(type,fn,false);
程序this指向是dom元素本身
- obj.attachEvent(‘onxxx’,fn);
程序this指向window
解决this指向问题 让this指向obj .call改变this指向
var div = document.getElenmentsByTagName('div')[0];
div.attachEvent('onclick',function(){
handle.call(div);
})
function handle(){
console.log(this);
}
- 封装兼容性的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 = null;
var div = document.getElenmentsByTagName('div')[0];
div.onclick = function(){
consoloe.log('a');
this.onclick = null;
}
- ele.removeEventListener(type,fn,false);
var div = document.getElenmentsByTagName('div')[0];
div.addEventListener('click',text,false);
function text(){
console.log('a');
}
div.removeEventListener('click',text,false); //匿名函数解除不了事件绑定
- ele.detachEvent(‘on’ + type,fn);
- 若绑定匿名函数,则无法解除
事件处理模式–事件冒泡、事件捕获
- 事件冒泡 false
结构上(非视觉上)嵌套关系的元素,辉存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素。(自底向上)
<div class="wrapper" style="width: 300px;height:300px;background-color:red">
<div class="content" style="width: 200px;height:200px;background-color:yellow">
<div class="box" style="width: 100px;height:100px;background-color:green"></div>
</div>
</div>
let wrapper = document.getElementsByClassName('wrapper')[0]
let content = document.getElementsByClassName('content')[0]
let 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);
box content wrapper
- 事件捕获 true
结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,即同一事件,自父元素捕获至子元素(事件源元素)。(自顶向下)
IE没有捕获事件
<div class="wrapper" style="width: 300px;height:300px;background-color:red">
<div class="content" style="width: 200px;height:200px;background-color:yellow">
<div class="box" style="width: 100px;height:100px;background-color:green"></div>
</div>
</div>
let wrapper = document.getElementsByClassName('wrapper')[0]
let content = document.getElementsByClassName('content')[0]
let box = document.getElementsByClassName('box')[0]
wrapper.addEventListener('click',function(){
console.log('wrapper')
},true);
content.addEventListener('click',function(){
console.log('content')
},true);
box.addEventListener('click',function(){
console.log('box')
},true);
wrapper content box
- 触发顺序,先捕获,后冒泡
<div class="wrapper" style="width: 300px;height:300px;background-color:red">
<div class="content" style="width: 200px;height:200px;background-color:yellow">
<div class="box" style="width: 100px;height:100px;background-color:green"></div>
</div>
</div>
let wrapper = document.getElementsByClassName('wrapper')[0]
let content = document.getElementsByClassName('content')[0]
let box = document.getElementsByClassName('box')[0]
wrapper.addEventListener('click',function(){
console.log('wrappermaopao')
},false);
content.addEventListener('click',function(){
console.log('contentmaopao')
},false);
box.addEventListener('click',function(){
console.log('boxmaopao')
},false);
wrapper.addEventListener('click',function(){
console.log('wrapperbu')
},true);
content.addEventListener('click',function(){
console.log('contentbu')
},true);
box.addEventListener('click',function(){
console.log('boxbu')
},true);
- focus blur chang submit reset select 等事件不冒泡
取消冒泡
事件函数中有一个参数 e/event 它是系统穿进来的参数 代表这个事件发生时的状态
- event.stopPropagation(); w3c标准
document.onclick = function(){
console.log('点击document事件') //默认冒泡 点哪都会执行这句
}
let div = document.getElementsByTagName('div')[0];
div.onclick = function(e){
e.stopPropagetion(); //阻止冒泡
this.style.backgroundColor = 'red';
}
- event.cancelBubble = true; IE标准 (谷歌也有)
document.onclick = function(){
console.log('点击document事件') //默认冒泡 点哪都会执行这句
}
let div = document.getElementsByTagName('div')[0];
div.onclick = function(e){
// e.stopPropagetion(); //阻止冒泡
e.cancelBubble = true;
this.style.backgroundColor = 'red';
}
- 封装函数
function stopBubble(event){
if(event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}
}
阻止默认事件
- 默认事件 – 表单提交 a标签跳转 右键菜单等
- return false; 以对象属性的方式注册的事件才生效(以句柄的方式生效 e.onclick)
document.oncontextmenu = function(){
console.log('a');
return false;
}
- event.preventDefault(); W3C标准
document.oncontextmenu = function(e){
console.log('a');
e.preventDefault();
}
- event.returnValue = false 兼容IE
document.oncontextmenu = function(e){
console.log('a');
e.returnValue = false;
}
- 封装函数 cancelHandler();
document.oncontextmenu = function(e){
console.log('a');
cancelHandler(e);
}
function cancelHandler(e){
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
}
事件对象
- event || window.event 用于IE
- 事件源对象
event.target 火狐
event.srcElement IE
chrome 两个都有
div.onclick = function(e){
let event = e || window.event;
let target = event.target || event.srcElement;
console.log(target);
}
事件委托
利用事件冒泡,和事件源对象进行处理
优点,性能,灵活 不需要一个个绑定,新添子元素不需要重新绑定
- 实现点击ul 中的li 输出这个li的值 (非常多的li)
let ul = document.getElementsByTagName('ul')[0];
ul.onclick = function(e){
let event = e || winodow.event;
let target = event.target || event.srcElement;
console.log(target.innerText);
}