链接:https://zhuanlan.zhihu.com/p/34760498
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
问题一览
- mouseover和mouseenter两个事件有什么区别?
- 移动端的click事件行为与PC端有什么不同?如何屏蔽掉这个不同?
- Event对象中,target和currentTarget的区别?
- 说一说什么是事件冒泡,如何阻止事件冒泡?如何阻止默认事件?
- 是否了解移动端的点击穿透,原理及解决方法?
- 是否了解事件委托?
- 什么是事件循环?
- css3中有哪些属性可以直接影响JS中的事件?(可以讲一下pointer-events和touch-action属性吗)
问题解答
1.mouseover和mouseenter两个事件有什么区别?
二者的区别是mouseenter不会冒泡(bubble)。
详细解释一下
当二者绑定的元素都没有子元素时,二者的行为是一致的。但是二者内部都包含子元素时,行为就不一样了。
在mouseover绑定的元素中,鼠标每次进入一个子元素就会触发一次mouseover事件,而mouseenter只会触发一次。
下面一篇博文中的例子写的很好,我就不自己写代码了。
前端面试题之mouseover和mouseenter的区别 - 优快云博客2.移动端的click事件行为与PC端有什么不同?如何屏蔽掉这个不同?
移动端的click事件会延迟300ms触发事件回调(只在部分手机浏览器上出现)。
为什么会这样?
因为手机浏览器中需要处理如翻页这样复杂的手势。在用户做翻页或双击放大等操作时,是先将手指触碰到屏幕(此时理应已经触发了click事件),然后再上下移动手指,浏览器开发厂商为了识别这种事件,所以加入了300ms延迟的处理。
解决方法
可以引入Fastclick.js来解决这个问题。它的原理是 FastClick 在检测到touchend事件的时候,会通过 DOM 自定义事件立即触发一个模拟click事件,并把浏览器在 300 毫秒之后真正触发的click事件阻止掉。
3.Event对象中,target和currentTarget的区别?
currentTarget是当事件遍历DOM时,标识事件的当前目标。它总是引用事件处理程序附加到的元素,而不是event.target,event.target标识事件发生的元素。
有个简单的验证方法,你会在下面的例子中看到e.currentTarget一直返回的是body元素,而e.target则随着你点击位置的不同而变化
<body>
<ul id="test">
<li>
<ul class="enter-sensitive">
<li>item 1-1</li>
<li>item 1-2</li>
</ul>
</li>
<li>
<ul class="enter-sensitive">
<li>item 2-1</li>
<li>item 2-2</li>
</ul>
</li>
</ul>
<script>
document.body.addEventListener('click', function (e) {
console.log(e.target, e.currentTarget)
})
</script>
</body>
4.说一说什么是事件冒泡,如何阻止事件冒泡?如何阻止默认事件?
事件冒泡是指 事件开始时由最具体的元素(文档中嵌套层次最深的那个节点)接受,然后逐级向上传播到较为不具体的节点(文档)。
阻止事件冒泡的方法。
调用当前事件对象的stopPropagation()方法
阻止默认事件
调用当前事件对象的preventDefault()方法
5.是否了解移动端的点击穿透,原理及解决方法?
有上面click事件300ms延迟的讲解,这个“点击穿透”就能好理解一些。
点击穿透是指在移动端,由于click事件延迟300ms触发,那么如果300ms内,页面显示变化(主要是指DOM的隐藏和显示)的话,会出现实际点击元素触发了touch事件,而300ms后该位置的实际元素又被再次触发了click事件的情况。
下面是我在网上找到的点击穿透的现象详细说明:
点击穿透现象有3种:
点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件。
蒙层的关闭按钮绑定的是touch事件,而按钮下面元素绑定的是click事件,touch事件触发之后,蒙层消失了,300ms后这个点的click事件fire,event的target自然就是按钮下面的元素,因为按钮跟蒙层一起消失了。
跨页面点击穿透问题:如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转。
因为 a标签跳转默认是click事件触发 ,所以原理和上面的完全相同。
另一种跨页面点击穿透问题:这次没有mask了,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了。
避免方法在上面的问题中已经说过,可以引入fastclick之类的插件来解决。
6.是否了解事件委托?
这道题通常情况下会有好几种引出方式,看面试官如何带节奏了~
比如,会问你如何给一个超长的商品列表中的每个商品绑定一个点击事件啊?如何解决大量事件绑定造成的内存开销问题啊?
其实,这些问题都是想确认你是否有事件委托的意识。
事件委托是指利用“事件冒泡”,只通过指定一个事件处理程序,来管理某一类型的所有事件。也就是说,当此事件处理程序被触发时,通过当前事件对象中的target来确认究竟是在哪个元素触发的事件,从而达到一次注册 处理多个元素触发事件的目的。
7.什么是事件循环
事件循环是一个大概念,想要讲透不是几句话可以说清的。当然如果面试官问到了,他的初衷也绝对不是想让你透彻的讲解一遍,只是想确认面试者对于JS运行机制的了解程度。
好,我试着笼统地概括一下。
JavaScript是单线程的,“主线程”负责执行所有的同步任务,一旦所有同步任务执行完成,则立即从“任务队列”中读取最优先的任务放到“主线程”中执行,如此循环往复。向“任务队列”插入的是一个个事件处理函数(确切的说是函数地址)或定时任务(setTimeout的回调)。
以上总结参考了以下两篇文章:
并发模型与事件循环

能说出JavaScript是单线程,还有任务队列(或说“事件队列”)的概念,基本就可以了。
8.css3中有哪些属性可以直接影响JS中的事件?(可以讲一下pointer-events和touch-action属性吗)
css3中有两个属性是可以直接影响到JS中的事件的,他们是pointer-events和touch-action。
pointer-events
CSS 属性指定在什么情况下 (如果有) 某个特定的图形元素可以成为鼠标事件的 target。当该属性值设定为none
时 表示鼠标事件“穿透”该元素并且指定该元素“下面”的任何东西。
需要注意的是,如果当前元素的pointer-events属性指定位none,但是当其后代元素的pointer-events
属性指定其他值时,鼠标事件可以指向后代元素,在这种情况下,鼠标事件将在捕获或冒泡阶段触发父元素的事件侦听器。
touch-action
用于指定某个给定的区域是否允许用户操作,以及如何响应用户操作(比如浏览器自带的划动、缩放等)。
最常见的用法是禁用元素(及其不可滚动的后代)上的所有手势,以使用自己提供的拖放和缩放行为(如地图或游戏表面)。
#map {
touch-action: none;
}
总结:现在很多框架(如Vue、React)已经将事件绑定和处理都封装了,如果你是框架的强依赖开发者的话,很多问题你可能并不会遇到,如你几乎不需要理解Event对象中的target。
但是话说回来,用人单位和面试官(有水平的那种)其实希望面试者是真正掌握JavaScript这门语言,而并不是掌握某某框架的使用方法,大家应该清楚其中的不同。
题外话:如果您觉得这篇文章对您有帮助,如果您对前端技术感兴趣,您可以关注公众号——“较真的前端”。那里有更多技术干货等着您。