这是两个都是鼠标移入事件,首先要明确的是**mouseover可以冒泡,而mouoseenter无法冒泡**,这是它们的最根本区别

示例说明

这两者间的区别可以明显体现在父子元素间

示例主要代码:

<div class="parent-over">mouserover<div class="son-over">son</div>
</div><div class="parent-enter">mouseenter<div class="son-enter">son</div>
</div>
const over = document.querySelector(".parent-over");
const enter = document.querySelector(".parent-enter");over.addEventListener("mouseover", function() {console.log("mouseover");
});
enter.addEventListener("mouseenter", function() {console.log("mouseenter");
});

通过以上代码构造两对父子元素,一个父亲元素绑定mouseover,另一个父亲元素绑定mouseenter

虽然mouseovermouseenter都是鼠标移入事件,但当鼠标在父子元素间移动时,左侧和右侧的鼠标移入事件触发的结果是不同的:

当鼠标进入左侧绑定了mouseover事件的父级元素时,会触发绑定在父元素的mouseover事件,当鼠标继续移动进入蓝色背景的子元素时,左侧的子元素会触发再次触发该事件,从左侧子元素移动回粉色区域时,父元素又会触发一次该事件(共3次)

而当鼠标进入右侧绑定了mouseenter的父级元素时,会触发绑定在父元素的mouseenter事件,但只要鼠标不离开右侧粉色区域,鼠标无论如何在父子元素间移动,都不会再触发该事件(除非鼠标离开右侧粉色区域后再进入)(共1次)

查看控制台打印的信息,左侧的mouseover被触发了3次,右侧被触发了1次

这两者的区别就是由**mouseover可以冒泡,而mouoseenter无法冒泡**导致的:

对于左侧:当鼠标第一次进入父元素时,自然会触发鼠标移入事件,执行一次事件处理函数,这是第1次;当鼠标继续移动进入子元素时,此时并没有在子元素绑定mouseover的事件处理函数,但由于mouseover会冒泡,因此向上冒泡到父元素时会触发绑定了处理函数的mouseover,这是第2次;当鼠标从子元素移动到父元素时,会再次触发该事件,因为此时认为是从父元素外的区域“进入”,这是第3次,所以共有3次

对于右侧:当鼠标第一次进入父元素时,自然会触发鼠标移入事件,执行一次事件处理函数,这是第1次;当鼠标移入子元素时,并不能触发事件,因为mouseenter不冒泡,因此不能触发父元素的mouseenter事件;当鼠标从子元素移动到父元素时,也不会触发事件,因为此时依然看作是在父元素中来回移动而已,所以只有1次

对于这两个鼠标移入事件,有两个对应的鼠标移出事件:
mouseover对应于mouseout
mouseenter对应于mouseleave

mouseoutmouseleave的根本区别在于前者可以冒泡,而后者不能,这点和两个鼠标移入事件类似

为什么要同时有两种鼠标移入(两种鼠标移出)事件?

这里给出我个人的思考

首先要知道mouseenter是在捕获阶段执行事件处理函数的,而不能在冒泡阶段过程中进行;mouseout是可以在捕获阶段和冒泡阶段选择一个阶段来执行事件处理函数的(默认为冒泡阶段)

我们可以阻断冒泡(stopPropagation()),而捕获是不可阻断的(当有事件被触发时,事件流的传播是从DOM树的最顶层的 document 向下传播寻找事件源的,当找到了事件源就会停止向下传播,而捕获的方向就是这个方向。当找到事件源后就要返回,这个过程就是冒泡阶段)

当父元素和子元素都要绑定鼠标移入事件时

mouseenter事件处理函数的执行是在捕获阶段进行的,假如子元素的mouseenter事件被触发了,事件流必然会经过其父元素,父元素此时也绑定了mouseenter事件,那么就必然会先触发父元素的mouseenter事件并执行对应的事件处理函数,然后再执行子元素上的事件处理函数。捕获阶段是不可阻断的,所以父元素和子元素的mouseenter事件同时被触发是不可避免的。有时我们只希望触发子元素的事件,这时就需要利用mouseover

mouseover可以冒泡,当父子元素都绑定了mouseover事件,如果希望触发子元素的mouseover事件时不触发父元素的mouseover事件,那么只需要利用stoppropagetion()阻止冒泡即可,这就可以实现mouseenter不能实现的(即无法避免在触发子元素鼠标移入事件时,父元素的鼠标移入事件也被触发的情况)(算是弥补mouseenter的“缺陷”)

当只有父元素绑定鼠标移入事件,而子元素不绑定时

mouseover默认是在冒泡过程中执行事件处理函数,而由于事件可以冒泡,当子元素的mouseover事件被触发后,也会触发父元素的mouseover事件。当我们在这时使用mouseover,因为子元素并没有绑定任何相关事件,如果我们不希望在鼠标移入子元素时触发父元素的mouseover事件,就必须为子元素特地去添加一个仅含有阻止冒泡操作的事件处理函数(如下),否则当鼠标移入子元素时就会触发一次父元素绑定的mouseover事件。这种情况下使用mouseenter是更加简练的方式——mouseenter不能冒泡,那么直接应用mouseenter则只会触发父元素,当鼠标进入子元素时,也不会再次触发父元素

// 仅含阻止子元素冒泡操作的事件处理函数
son.addListener("mouseover", function(e) {e.stopPropagation();
});

当只有子元素绑定鼠标移入事件,而父元素不绑定时

使用哪个效果都一样

综上,当父子元素都需要绑定鼠标移入事件,并希望独立地触发对应元素的事件时(当移入父元素时只触发父元素的,当移入子元素时只触发子元素的),应当选用mouseover事件,并在子元素中使用stopPropagation()来阻止冒泡;
当只有父元素需要绑定鼠标移入事件,并希望移入父元素区域后不要反复触发事件时,使用mouseenter事件会比较方便,因为如果使用会冒泡的mouseover事件,需要额外为子元素添加仅含阻止冒泡操作的事件处理函数,会增加内存开销

(对于mouseoutmouseleave的分析类似以上)

引发的关于click的思考

clickmouseenter相反,click只能在冒泡阶段过程中执行事件处理函数,而不能在捕获阶段过程中。这又是为什么呢?以下给出我的个人见解

对于点击事件,我们希望的是一种“精准的点击效果”,也就是当我们点击了一个元素,我们往往希望的是只触发绑定在这个元素上的点击事件,而不触发其他元素的点击事件(往往是父元素的)。对于父子元素都绑定了点击事件的情况来说,如果要实现父子元素的点击事件独立触发,只需要阻止子元素的点击事件冒泡即可。那如果click可以在捕获阶段过程中执行事件处理函数应该也不影响吧?

接下来我假设click可以在捕获阶段过程中执行事件处理函数

我们知道,大多数事件都可以选择在两个阶段中的一个执行事件处理函数,默认都是在冒泡阶段。可以通过将addEventListener()capture参数设置为true实现在捕获阶段执行处理函数,那么如果将click设置在捕获阶段执行事件处理函数,其父元素如果有点击事件的话,就会总是在子元素点击事件处理函数执行前执行父元素的执行函数。对于点击效果来说,应该是“点哪从哪开始触发”,捕获阶段的效果显然是,“点哪随便从哪有绑定点击事件的地方开始触发”,这时如果祖先元素也有点击事件,整个点击效果将会十分不符合预期,鼠标本来点击的元素绑定的事件处理函数却在最后才执行(或许还会因为其他点击事件的作用而根本无法执行,比如某个父级元素的点击事件包含页面跳转操作,或删除点击的目标子元素的操作)

由此可见,click根本没有在捕获阶段执行事件处理函数的需要

文章源码:https://gitee.com/thisismyaddress/bocheng-blogs/tree/master/js/mousemover和mouseenter

参考:

https://developer.mozilla.org/zh-CN/docs/Web/API/Event/stopPropagation
https://developer.mozilla.org/zh-CN/docs/Web/API/Element/mouseenter_event
https://developer.mozilla.org/en-US/docs/Web/API/Element/mouseover_event

由mouseover和mouseenter引发的思考相关推荐

  1. mouseover与mouseenter,mouseout与mouseleave的区别

    mouseover与mouseenter 不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件. 只有在鼠标指针穿过被选元素时,才会触发 mouseenter 事件. mouseou ...

  2. JAVA-OPTS引发的思考

    JAVA-OPTS引发的思考 我们在性能测试过程中,经常要修改应用的JAVA-OPTS参数.修改这些参数,不单单是修改这些数字,本着知其所以然的态度,我们要知道这些参数背后的意义. 常见的JAVA-O ...

  3. 一个小程序引发的思考

    既然是一个小程序引发的思考,那么我们就先看看这个小程序,看看他有何神奇之处: namespace ConsoleApplication1 {class Program{static void Main ...

  4. 由“递归遍历二叉树”引发的思考

    由"递归遍历二叉树"引发的思考 递归的用法我感觉自己已经掌握了,可是今天在递归遍历二叉树时,它又迷一样令我费解.我本人在算法这一块很薄弱,所以想把这个问题发出来,希望有大神能够为我 ...

  5. 由一行文本输入框引发的思考

      文章是关于React组件之表单单行文本输入框的一些思考.可能大家第一反应都是,不就是一行<input/>嘛,没什么特别的吧?如果说到输入框的值的话,可能圈子里上大多数封装好的React ...

  6. 由熊猫烧香引发的思考

    由熊猫烧香引发的思考 早期的计算机病毒诞生,作者是以技术炫耀为主,编写这类病毒需要更深入的了解系统及网络技术,开发功底也要更深厚.现阶段,一个合格的程序员,制造出具备破坏性的代码,已经不怎么难.甚至, ...

  7. Spring之LoadTimeWeaver——一个需求引发的思考---转

    原文地址:http://www.myexception.cn/software-architecture-design/602651.html Spring之LoadTimeWeaver--一个需求引 ...

  8. jQuery面试题-区别mouseover和mouseenter的不同之处(看了也许对你有好处)

    文章目录 1.简单阐述mouseover和mouseenter的不同之处 2.代码实例测试 3.效果图 1.简单阐述mouseover和mouseenter的不同之处 mouseover:在移入子元素 ...

  9. 由SecureCRT引发的思考和学习

    由SecureCRT引发的思考和学习 http://mp.weixin.qq.com/s?__biz=MzAxOTAzMDEwMA==&mid=2652500597&idx=1& ...

最新文章

  1. 快速排序算法(基于Java实现)
  2. a bytes-like object is required, not 'str' pickle.loads pickle.dumps
  3. 【项目管理】ITTO-质量管理
  4. @Styles.Render
  5. 《重构-改善既有代码的设计》学习笔记----Extract Method(提炼函数)
  6. 用户 'sa' 登录失败。 连接SQL2000出现的问题。
  7. STM32智能锁指纹锁密码锁WIFI远程开锁微信小程序临时密码源码PCBA方案
  8. 深度学习入门笔记(二十一):经典神经网络(残差网络ResNets)
  9. 胡震宁先生的《职业生涯规划》
  10. java id 锁_java 多线程synchronized同步锁锁住相同用户Id
  11. App Tamer for Mac(CPU优化电池管理工具)
  12. 一种重复命名自动更名机制
  13. (十八)Flink Table API SQL 编程指南 Table API 和Datastream API 集成
  14. 路由器备份文件查看 Android,【教程】用安卓系统 手机查看路由U盘内容的方法...
  15. 云服务器的地域怎么选择?
  16. Polar vector and axial vector(极矢量和轴向矢量)
  17. 第八章 我国农村商品流通
  18. 中海达手簿软件Hi-Survey Road提示:非认证设备,不支持RTK采集!——授之以渔
  19. Python版冈萨雷斯 V1.0
  20. linux如何停止自启动运行脚本

热门文章

  1. Android 获取应用列表
  2. web端上传图片的几种方式
  3. Mysql 安装,及其闪退的问题解决
  4. 做题遇到的trick和想法
  5. oracle 存储过程语法例子
  6. JBOSS4.0.2集群配置
  7. 虚拟号的运营商一般是哪家的?你知道吗?
  8. Threejs 中的后期处理
  9. 输出日期为2021年的第几天(switch...case)
  10. android MediaPlayer 完成播放后无法再次播放