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),对应从外界移入containerconainer元素本身,对应从其子元素上移入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) { |