DOM事件
简单来说,事件就是定义了一些Javascript函数,使他们能够响应页面元素发生的变化。比如用户在元素上方点击了鼠标按钮click事件,用户把鼠标移动到了元素上方mouseover事件。
事件流
一个事件的生命周期有三个阶段:捕捉,目标,冒泡。
1.捕捉阶段(大到小)
当某个事件被触发时,浏览器会找到涉及的元素。涉及的元素称为目标。浏览器会找到body元素和目标之间所有元素并分别检查它们,看其有没有事件绑定。浏览器会先触发外层事件处理器,最后才会轮到目标处理器。document->html->body->div
2.当捕捉阶段完成后,浏览器会触发目标元素上任何已添加的事件类型监听器,这里的先后顺序是按照事件定义的先后顺序来的。
3.冒泡阶段(小到大)
冒泡阶段的顺序与捕捉阶段的顺序刚好相反,在此阶段,浏览器会优先处理目标的事件处理器,然后一层层往外处理其余的事件处理器。
div->body->html->document
阻止事件冒泡
event.stopPropagation();//1.阻止事件冒泡,但不会阻止默认行为
return false;//2.阻止事件冒泡,也阻止了默认行为
event.preventDefault();//3.阻止默认行为,不阻止事件冒泡(可阻止鼠标右击出现菜单这个默认事件)
事件委托
事件委托是利用事件冒泡原理,让节点的父级代为执行事件。而不需要遍历元素的子节点,大大减少dom操作。
事件委托的优点:
- 与DOM节点交互一次,减少与DOM交互次数,起到性能优化作用;
- 减少占用空间函数对象个数(仅对父级添加一个函数对象),节省内存空间;
- 新增子对象时,能动态绑定事件。
举例:
实现鼠标移入li变红,移出li变白。
不用事件委托的写法:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>事件代理</title>
</head>
<body>
<input type="button" name="" id="btn" value="添加对象" />
<ul id="ul1" style="list-style: none;">
<li>第1个li</li>
<li>第2个li</li>
<li>第3个li</li>
<li>第4个li</li>
</ul>
<script>
var oBtn = document.getElementById("btn");
var oUl = document.getElementById("ul1");
var aLi = oUl.getElementsByTagName('li');
// for循环遍历li节点:鼠标移入变红,移出变白
for(var i=0; i<aLi.length;i++){
aLi[i].onmouseover = function(){
this.style.background = 'red';
};
aLi[i].onmouseout = function(){
this.style.background = '#fff';
}
}
// 添加新节点
oBtn.onclick = function(){
var oLi = document.createElement('li');
oLi.innerHTML = '新添加的第'+ (aLi.length+1)+'个li';
oUl.appendChild(oLi);
};
</script>
</body>
</html>
利用事件委托的方式:
新添加的子元素是带有事件效果的,当用事件委托的时候,根本就不需要去遍历元素的子节点,只需要给父级元素添加事件,其他的都是在js里面的执行,大大的减少dom操作。
<input type="button" name="" id="btn" value="添加对象" />
<ul id="ul1" style="list-style: none;">
<li>第1个li</li>
<li>第2个li</li>
<li>第3个li</li>
<li>第4个li</li>
</ul>
<script>
var oBtn = document.getElementById("btn");
var oUl = document.getElementById("ul1");
var aLi = oUl.getElementsByTagName('li');
oUl.onmouseover = function (ev) {
var ev = window.event; // 获取当前事件源
var target = ev.target; // 兼容IE和标准浏览器
// 判断目标标签是否为li,防止点击ul出发事件
if (target.nodeName.toLowerCase() == 'li') {
target.style.background = "red";
}
};
oUl.onmouseout = function (ev) {
var ev =window.event; // 获取当前事件源
var target = ev.target; // 兼容IE和标准浏览器
// 判断目标标签是否为li,防止点击ul出发事件
if (target.nodeName.toLowerCase() == 'li') {
target.style.background = "#fff";
}
};
//添加新节点
oBtn.onclick = function () {
var oLi = document.createElement('li');
oLi.innerHTML = '新添加的第' + (aLi.length + 1) + '个li';
oUl.appendChild(oLi);
};
</script>
这里用父级元素ul做事件处理,当li被点击时,由于冒泡原理,时间就会冒泡到ul上,因为ul上有点击事件,所以事件就会被触发。