八 、冒泡捕获流、事件与事件源对象、事件委托
一、冒泡捕获流
事件流:页面中接收事件的顺序。
IE提出的 事件冒泡流(Event Bubbling);
网景公司提出的 事件捕获流(Event Capturing)
三个阶段的规范:
- DOM0:onxxx句柄绑定事件的形式
- DOM1:没有定义这个事件模型
- DOM2:addEventListener(type, fn, false),removeEventListener()->w3c规范
事件流三个阶段:
- 捕获阶段
- 目标阶段
- 冒泡阶段
通过点击事件来说明事件流的冒泡和捕获过程:
冒泡过程:点击事件源,事件源的绑定事件正常执行,再往父级一级一级传递相同事件,直到顶层。
捕获过程:点击事件源,事件源的绑定事件先不执行,找到相同事件类型的顶层父级,一级一级向内触发,一直到事件源正常执行。
二、事件与事件源对象
事件对象:事件触发后的详细信息,会包装成一个对象——>传到事件处理函数的参数中去(这个参数可以起任意名字,一般叫e,ev,event…)。
打印一下事件对象:
注:对象前面的PointEvent是这个事件对象的构造函数名。
Event对象 = new PointEvent();
IE的事件对象不在事件处理函数内部,在window上,为:window.event
事件对象中的两个属性srcElement(IE中只有srcElement),target(火狐中只有target),都指向事件源对象。
所以不仅事件对象需要兼容性写法,事件源对象也需要兼容性写法。
事件源的兼容性:
ele.onxx = function(e){
// 事件对象兼容性
// 事件源对象兼容性
var e = e || window.event,
tar = e.target || e.srcElement;
}
三、事件委托(事件代理)
事件委托利用事件冒泡,可以只使用一个事件处理程序来管理一种类型的事件。
用途:
- 想要在大量子元素中单击任何一个都可以运行一段代码,可以将事件监听器设置在其父节点上,并让子节点上发生的事件冒泡到父节点上,而不是每个子节点单独设置事件监听器。
- 自身不亲自绑定事件,让父级来进行绑定,通过冒泡机制来触发父级上的绑定的事件处理函数,然后通过事件源对象e.targete||e.srcElement来获取子元素节点
点击button增加li元素,并增加对应标签内容;同时点击不同li输出对应标签内容
<body>
<button>增加li</button>
<ul class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
</ul>
<script>
// 获取元素
var oList = document.getElementsByTagName('ul')[0],
oLi = document.getElementsByTagName('li'),
oBtn = document.getElementsByTagName('button')[0];
// 点击 button增加 li 元素,并增加对应标签内容;
// 同时点击不同 li 输出对应标签内容
// 把事件委托给父级触发,触发后通过事件源对象来找到点击元素
oList.onclick = function(e){
var e = e || window.event,
tar = e.target || e.srcElement;
// 打印对应li的标签内容
console.log(tar.innerText);
};
oBtn.addEventListener('click', function(){
var li = document.createElement('li');
li.innerText = oLi.length + 1;
oList.appendChild(li);
}, false);
</script>
</body>
输出li对应的下标,核心方法:
Array.prototype.index.call(DOM对象集合,当前事件源)
indexOf() 方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
// 获取元素
var oList = document.getElementsByTagName('ul')[0],
oLi = document.getElementsByTagName('li');
oList.onclick = function(e){
var e = e || window.event,
tar = e.target || e.srcElement;
// 现在我们想要获取这里 li 元素的下标
// 方法1:遍历 li 列表,当 li 元素与 tar 元素相同时,打印这个 li
// 可以成功不推荐,若 li 很多,遍历非常耗能
// 方法2:
// 让 oLi 继承 Array.prototype.indexOf 方法,从而获取事件源对象的下标
var index = Array.prototype.indexOf.call(oLi, tar);
console.log(index);
}