JS23 mouseover与mouseenter
mouseover
/mouseout
与mouseenter
/mouseleave
的区别以及模拟。
区别
mouseover
和mouseout
成对使用,事件会冒泡,当鼠标指针穿过被选元素子元素时,也会触发事件。
mouseenter
和mouseleave
成对使用,事件不会冒泡,只有在鼠标指针穿过被选元素时,才会触发mouseleave
事件。
也就是说,假设把mouseover
/mouseout
事件绑定到了父元素,那么它其中的任何子元素只要发生了mouseover
/mouseout
事件,同时也会触发父元素的mouseover
/mouseout
事件,父元素的父元素也会触发……然后一直向上,就像池塘的气泡一样一直往上冒。
而mouseenter
/mouseleave
不会发生事件冒泡,属于传统思维上的鼠标进出。
用mouseover
模拟mouseenter
1 | <div id="container"> |
mouseover
因为具有冒泡的性质,在子元素内移动的时候父元素的mouseover
会被频繁触发。为了避免这个状况,可以使用mouseenter
代替。
也可以使用mouseover
结合relatedTarget
模拟mouseenter
的效果,对于mouseover
事件来说,relatedTarget
是鼠标移动目标节点时所离开的那个节点,对于mouseout
事件时,改属性是离开目标时鼠标指针进入的节点
对于上面container
的mouseover
事件,它的relatedTarget
值可能是:
container
的父元素(即body
),对应从外界移入container
conainer
元素本身,对应从其子元素上移入container
- 子元素本身,对应从
child1
移入child2
要模拟mouseenter
,relatedTarget
值只能是第一种情况,但是我们不能这样直接判断,这是因为有可能container
的父元素不一定在各个方向包裹container
,也就是说我们要判断的父元素可能是祖先元素的某一个,也就无法准确判断relatedTarget
是哪个元素,所以需要通过排除2、3是更好的选择
1 | const container = document.querySelector('#container'), |
判断父子节点包含关系使用了ele.contains
这个API,用来表示传入的节点是否为改节点的后代节点。
用mouseout
模拟mouseleave
原理是一样的。
可以直接封装为一个函数,注意this
就是container
,也就是我们绑定事件的对象,可以使用e.currentTarget
来代替
1 | function simulateEnterOrLeave(cb) { |