事件委托或事件代理,就是利用事件冒泡,值得是指定一个事件处理,就可以管理某一类型的所有事件。
- 111
- 222
- 333
- 444
实现点击li的时候,弹出123
window.onload = function(){
var oUl = document.getElementById("ul1");
var aLi = oUl.getElementsByTagName('li');
for(var i=0;i
上面的代码需要多次操dom,用事件代理的方式实现
window.onload = function(){
var oUl = document.getElementById("ul1");
oUl.onclick = function(){
alert(123);
}
}
用父级ul做事件处理,当点击li的时候,由于冒泡原理,事件就冒泡的ul上。但是点击ul的时候也会触发事件。我们用event提供的target来解决(IE中是srcElement)来获取节点的位置,我们并不知道节点的名字是什么,可以用nodeName来获取具体的标签名,这是返回的是大写,我们做好转化成小写来进行比较。
window.onload = function(){
var oUl = document.getElementById("ul1");
oUl.onclick = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase()=='li'){
alert(124);
alert(target.innerHTML);
}
}
}
这样写的话只有点击li的时候会触发事件,点击ul的时候不会。
在FireFox浏览器中,事件绑定的函数要获取到事件本身,需要从函数中传入,而IE等浏览器则可以直接使用event或者window.event得到事件本身。
window.onload = function(){
var Add = document.getElementById('add');
var Remove = document.getElementById('remove');
var Move = document.getElementById('move');
var Select = document.getElementById('select');
Add.onclick = function(){
alert('添加');
}
Remove.onclick = function(){
alert('删除');
}
Move.onclick = function(){
alert('移动');
}
Select.onclick = function(){
alert('选择');
}
}
普通的方法将要操作四次dom,下面用事件委托进行优化
window.onload = function(){
var oBox = document.getElementById('box');
oBox.onclick = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase()=='input'){
switch(target.id){
case 'add':
alert('添加');
break;
case 'remove':
alert('删除');
break;
case 'move':
alert('移动');
break;
case 'select':
alert('选择');
break;
}
}
}
}
一次dom操作就可以完成所有效果
上面讨论的都是已有的节点,那么新添加的节点,能实现事件吗
一个正常添加节点的方法:
- 111
- 222
- 333
- 444
完成鼠标移入,li的背景色变成红色,移出变成白色,点击按钮新添加一个li
window.onload = function(){
var oBtn = document.getElementById('btn');
var oUl = document.getElementById('ul1');
var aLi = oUl.getElementsByTagName('li');
var num = 4;
for(var i=0;i
但是我们发现新添加的li是没有事件的,说明添加子节点的时候,事件并没有同时被添加进去。一般的解决方法是,将for循环用一个函数包起来,命名为mHover。
window.onload = function(){
var oBtn = document.getElementById('btn');
var oUl = document.getElementById('ul1');
var aLi = oUl.getElementsByTagName('li');
var num = 4;
function mHover(){
for(var i=0;i
上面的方法虽然实现了功能,但是增加了dom操作,下面用事件委托的方式优化。
window.onload = function(){
var oBtn = document.getElementById('btn');
var oUl = document.getElementById('ul1');
var aLi = oUl.getElementsByTagName('li');
var num = 4;
oUl.onmouseover = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase=='li'){
target.style.background='red';
}
}
oUl.onmouseout = funtion(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase=='li'){
target.style.background='#fff';
}
}
oBtn.onclick = function(){
num++;
var oLi = document.createElement('li');
oLi.innerHtml = 111*num;
oUl.appendChild(oLi);
}
}
上面是用事件委托的方式,新添加的子元素是带有事件效果的,我们可以发现,当用事件委托的时候,根本就不需要去遍历元素的子节点,只需要给父级元素添加事件就好了,其他的都可以在js里面执行,这样可以大大的减少dom操作,这才是事件委托的精髓。
ul>li>div>p,div占满li,p占满div,还是给ul绑定事件,怎么判断是点击是li,e.target可能是p,也可能是div,怎么判断?
-
111111111
-
22222222222
-
333333333333
- 444444444444
window.onload = function(){
var oUl = document.getElementById('test');
oUl.onclick = function(ev){
var target = ev.target;
while(target!==oUl){
if(target.tagName.toLowerCase()=='li'){
console.log('li click');
break;
}
target = target.parentNode;
}
}
}
核心在while循环部分,从里往外冒泡,知道currentTarget为止,当target是li的时候,就可以执行相应的事件了,终止循环。
click,mousedown,mouseup,keydown,keyup,keypress