「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
问答(分析在最后)
这个问题主要考察基础知识,我一般喜欢这样问:
- 对DOM事件流你是怎么理解的?
- 事件冒泡和事件捕获具体的理解?
- 举个例子?
- 那怎么解决事件冒泡所引发的问题呢?
- 那在解释下事件委托?
Q:对DOM事件流你是怎么理解的?
A:事件流也叫事件传播,DOM2级事件规定事件流的三个阶段,分别是事件捕获阶段,目标阶段,事件冒泡阶段。 触发顺序先是事件捕获,在这个阶段可以截获事件做一些操作。 然后到目标阶段,在此阶段一般不做处理。 最后到冒泡阶段,可以在这个阶段对事件做出响应。
回答完后,引出了事件捕获和冒泡,问具体的理解?
Q:事件冒泡和事件捕获具体的理解?
事件冒泡是当某个元素的某类型事件触发时,它的父元素同类型的事件也会被触发,一直触发到根元素上。从确定的元素到不确定的元素。 事件捕获的思想是从根元素一直到事件源,用意是在事件到达预定目标之前就捕获它。
Q:追问:举个例子?
比如,现在有一个简单的H5页面,里面有3个嵌套元素,外层from,内层div,最内层p,每一层都有onclick事件,在点击最内层的p标签时,会依次运行onclick,直到文档对象。这个过程就是冒泡。
当我点击p标签时,首先会通过事件流的捕获阶段找到p元素,这个过程叫事件捕获,找到后触发目标阶段,然后上升到冒泡阶段,开始事件调用。
Q:追问:ok,那怎么解决事件冒泡所引发的问题呢?
A:可以使用stopPropagation()阻止冒泡或者也可以通过事件委托处理。
Q:那在解释下事件委托?
A:利用事件冒泡,只指定一个事件处理程序,管理某一类型的所有事件。 假如最内层有多个P标签,都有onclick事件,给它的父元素div绑定事件,代理子元素的点击事件,然后通过event对象提供的target属性,取到具体的节点进行操作。
事件委托减少了事件注册,节省内存占用,适合动态添加元素。
分析
事件流的三个阶段,捕获、目标、冒泡
事件冒泡演示代码
<style>
body * { margin: 10px; border: 1px solid blue;
}
</style>
<form onclick="alert('form')">
FORM
<div onclick="alert('div')">
DIV
<p onclick="alert('p')">P</p>
</div>
</form>
单击内部<p> 运行onclick事件,将看到 alert:p→ div→ form:
这个过程被称为“冒泡”,因为事件像水中的气泡一样从内部元素向上通过父元素“冒泡”。
注意:几乎所有的事件都会冒泡,也有例外,例如focus。
停止冒泡演示代码
<body onclick="alert(`body点击`)">
<button onclick="event.stopPropagation();alert('button点击')">点我</button>
</body>
此时点击button,只有alert按钮点击,不会出现body点击。
事件委托演示代码
<ul id="parent">
<li class="child">one</li>
<li class="child">two</li>
<li class="child">three</li>
</ul>
<script type="text/javascript">
//父元素
var dom= document.getElementById('parent');
//父元素绑定事件,代理子元素的点击事件
dom.onclick= function(event) {
var event= event || window.event;
var curTarget= event.target || event.srcElement;
if (curTarget.tagName.toLowerCase() == 'li') {
//事件处理
}
}
</script>
优点:
- 节省内存占用,减少事件注册。
- 新增子对象无需再次绑定事件,适合动态添加
局限性:
- focus、blur 之类的事件本身没有事件冒泡机制,所以无法委托
- mousemove、mouseout 这样的事件,虽然有事件冒泡,但是只能不断通过位置去计算定位,对性能消耗高,不适合事件委托