关键词:父子元素关系 mouseout mouseover 事件 事件冒泡
初期代码:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <script src="jquery.js"></script> 5 <meta charset="utf-8"> 6 <title>mouseover mouseout</title> 7 <style type="text/css" media="screen"> 8 .parent{ 9 width:200px; 10 height:200px; 11 background:black; 12 } 13 .child{ 14 width:100px; 15 height:100px; 16 background:pink; 17 } 18 .a1{ 19 width:40px; 20 height:40px; 21 background:orange; 22 display:none; 23 } 24 25 26 </style> 27 </head> 28 <body> 29 <div class="parent"> 30 <div class="child"></div> 31 <div class="a1"></div> 32 </div> 33 34 35 36 37 38 <script> 39 $(‘.parent‘).on(‘mouseover‘,function(e){ 40 41 42 $(‘.a1‘).show(1000); 43 44 }); 45 46 $(‘.parent‘).on(‘mouseout‘,function(e){ 47 48 49 $(‘.a1‘).css(‘display‘,‘none‘); 50 51 }); 52 53 54 55 </script> 56 </body> 57 </html>
我想实现的目标:当鼠标进入黑色框时,橙色框执行淡入动画;当黑色框范围移动的时候(即使经过粉色框,动画仍然不被触发);当鼠标移出的时候,橙色方块消失。
遇到的问题阐述:当鼠标移入黑色框的时候,橙色框执行淡入动画,但是当鼠标从黑色框经过粉色框的时候,橙色框就消失了,然后又执行一遍淡入动画。当鼠标从粉色框移出到黑色框的时候,橙色框的淡入动画又被执行。这不是我想要的。
首先我们解释一下原因,为什么会出现这些问题。
当鼠标从黑色框移到粉色框的时候,此时黑色框的mouseout的被触发,又由于事件冒泡,黑色框的mouseover事件随即被触发,所以实际上,橙色框先消失,然后立即执行淡入动画。这也就是我们看到的过程。
当鼠标从粉色框移到黑色框的时候,此时黑色框的mouseout又被触发(因为不论鼠标穿过被选元素或其子元素,都触发 mouseover 事件),同时mouseover也被触发,所以又出现了再次执行淡入效果的过程。
方法一:用mouseleave/mouseout代替mouseover/mouseout【最佳方法】
先看一下mouseout&mouseover与mouseleave&mouseenter用法上的区别
mouseover与mouseenter
不论鼠标指针穿过被选元素或其子元素,都会触发 mouseover 事件。
只有在鼠标指针从元素外穿入被选元素(到元素内)时,才会触发 mouseenter 事件。
mouseout与mouseleave
不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件。
只有在鼠标指针从元素内穿出被选元素(到元素外)时,才会触发 mouseleave 事件。
可以看一个简单的例子看看二者的区别
所以改进的代码可以为
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <script src="jquery.js"></script> 5 <meta charset="utf-8"> 6 <title>mouseover mouseout</title> 7 <style type="text/css" media="screen"> 8 .parent{ 9 width:200px; 10 height:200px; 11 background:black; 12 } 13 .child{ 14 width:100px; 15 height:100px; 16 background:pink; 17 } 18 .a1{ 19 width:40px; 20 height:40px; 21 background:orange; 22 display:none; 23 } 24 </style> 25 </head> 26 27 <body> 28 <div class="parent"> 29 <div class="child"></div> 30 <div class="a1"></div> 31 </div> 32 33 <script> 34 $(‘.parent‘).on(‘mouseenter‘,function(e){ 35 36 37 $(‘.a1‘).show(1000); 38 39 }); 40 41 $(‘.parent‘).on(‘mouseleave‘,function(e){ 42 43 44 $(‘.a1‘).css(‘display‘,‘none‘); 45 46 }); 47 </script> 48 </body> 49 </html>
方法二:利用e.stopPropagation()阻止事件进一步传播
e.stopPropagation()会终止事件在传播过程的捕获、目标处理或起泡阶段进一步传播。调用该方法后,该节点上处理该事件的处理程序将被调用,事件不再被分派到其他节点。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <script src="jquery.js"></script> 5 <meta charset="utf-8"> 6 <title>mouseover mouseout</title> 7 <style type="text/css" media="screen"> 8 .parent{ 9 width:200px; 10 height:200px; 11 background:black; 12 } 13 .child{ 14 width:100px; 15 height:100px; 16 background:pink; 17 } 18 .a1{ 19 width:40px; 20 height:40px; 21 background:orange; 22 display:none; 23 } 24 25 26 </style> 27 </head> 28 <body> 29 <div class="parent"> 30 <div class="child"></div> 31 <div class="a1"></div> 32 </div> 33 34 <script> 35 $(‘.parent‘).on(‘mouseover‘,function(e){ 36 $(‘.a1‘).show(1000); 37 38 }); 39 40 $(‘.parent‘).on(‘mouseout‘,function(e){ 41 $(‘.a1‘).css(‘display‘,‘none‘); 42 43 }); 44 45 $(‘.child‘).on(‘mouseover‘,function(e){ 46 e.stopPropagation(); 47 $(‘.a1‘).css(‘display‘,‘block‘); 48 //这是保证动画体的末状态不变 49 }); 50 51 $(‘.child‘).on(‘mouseout‘,function(e){ 52 e.stopPropagation(); 53 //防止从粉色框移出到黑色框时再次触发其他事件 54 }) 55 56 57 58 </script> 59 </body> 60 </html>
拓展思考:
1.如果子元素过多怎么办,难道每个都要去绑定e.stopPropagation()?
用jquery的一个选择器.children(),比如$(‘.parent‘).children()。获得匹配元素集合中每个元素的子元素。
备注:这篇文章中遇到同样的问题,但我并没怎么看懂,而且觉得有点麻烦,逻辑较繁重。同学们可以作参考。