用on给动态添加的元素绑定hover事件,没有生效的解决

博客讲述了动态加载dom节点后用jQuery绑定hover事件未生效的问题。分析发现,JQuery中hover()是对mouseenter和mouseleave的封装,原生event无hover事件,传参hover无效果。可绑定mouseenter和mouseleave事件,用类名toggle样式或在map里让事件对应function解决。

1.需求:经常要动态加载dom节点,加载之后的节点当然也会有一些绑定事件的需求,今天给一个事件绑定hover,用jQuery,竟然没有生效。先上没有生效的代码 

$('ul.course_lists').on('hover','li',function(){ 
      // mouseenter dosomething 
},function(){
      // mouseleave dosomething
});

2.问题出在哪里了?

  • on函数传的参数不对?查查文档呗,我看或不看他,他都在那里,我看他,或许可以帮助我解决问题,我不看他,依旧稀里糊涂
  • 先看语法
$(selector).on(event,childSelector,data,function,map) 
  • 很明显了,在传递到里面的参数中,只看到可以传一个function,而我传了两个函数

 3.分析

  在JQuery中,hover()函数本身是对 mouseenter && mouseleave 的封装,然而在原生event中,并没有hover这一事件,所以在传递参数hover时,并不会有任何的效果。

  如果我想绑定类似hover的效果,可以绑定两个事件mouseenter && mouseleave + 一个function ,样式就用类名来toggle,也可以在map里面,一个事件对应一个function

 4.代码来了

  •   绑定两个事件

复制代码

 
// js
$('ul.course_lists').on('mouseenter mouseleave','li',function(){ 
      $(this).toggleClass('border_color');
});

// css
.border_color{
    border-color:#ccc;    
}

li{
  border:1px solid #fff;
}

复制代码

  • map

复制代码

$('ul.course_lists li').on({
    mouseenter:function(){
        $(this).css('border-color','#ccc');
    },
    mouseleave:function(){
        $(this).css('border-color','#fff');    
    }
});

复制代码

5.搞定,but,on()方法不要再出错了! 

<think>我们之前尝试通过给容器添加圆角和overflow:hidden来解决圆角闪烁问题,但问题仍然出现在左侧。这可能是由于在动画过程中,某些轮播项(特别是那些位于左侧的项)在变换时超出了容器的边界,导致容器的圆角被覆盖或穿透。解决方案:1.确保容器(.fp-carousel-container)的overflow:hidden和border-radius生效,并且能够正确裁剪子元素。2.调整轮播项的位置变换,确保它们不会在动画过程中突破容器的边界。然而,由于轮播项使用绝对定位并进行了复杂的平移变换,可能在某些情况下(比如变换过程中)超出容器。我们可以尝试以下方法:-给容器添加一个额外的包裹层,专门用于圆角裁剪。-或者,给每个轮播项设置一个父级元素,该父级元素具有圆角和overflow:hidden,但这样可能会影响3D效果。另一种思路是:确保所有轮播项在变换时都不会超出容器的圆角边界。我们可以通过调整轮播项的位置计算,让它们始终在容器内,但这样可能会限制布局。经过分析,最可靠的方法是在容器上设置足够的裁剪属性。我们已经设置了`overflow:hidden`和`border-radius`,但问题仍然存在,可能是由于浏览器渲染性能问题,或者是因为在变换过程中,元素在合成层之外被绘制。我们可以尝试强制容器创建新的合成层,这样裁剪和变换可能会更平滑。使用CSS属性`transform:translateZ(0)`可以触发硬件加速,并可能解决渲染问题。修改`.fp-carousel-container`的样式:```css.fp-carousel-module.fp-carousel-container{/*已有样式*/transform:translateZ(0);/*触发硬件加速*/-webkit-backface-visibility:hidden;/*可选,避免闪烁*/backface-visibility:hidden;}```同时,确保容器和轮播模块的圆角一致,并且容器正确裁剪。另外,我们注意到在`.fp-carousel-item`上已经设置了`overflow:hidden`,但容器裁剪可能还不够强。我们可以尝试给轮播模块(.fp-carousel-module)也设置`overflow:hidden`和圆角,以双重保险。如果问题仍然存在,我们可能需要调整轮播项的位置变换公式,避免它们出现在容器的边缘外部。但考虑到我们的布局是居中然后平移,可能难以避免。另一种可能性:在变换过程中,轮播项可能会因为缩放和模糊效果而超出容器,特别是在使用`filter:blur()`时,模糊效果会向外扩散,可能超出容器的边界。我们可以尝试在容器上设置`isolation:isolate`(已经设置)来创建新的层叠上下文,并确保模糊效果被裁剪。如果以上方法都不行,我们可以尝试给容器添加一个伪元素,覆盖在容器的四个角,用与背景相同的颜色来遮盖超出的部分,但这需要知道背景色,且不是通用解决方案。由于问题描述为左侧圆角闪烁,我们可以重点检查左侧的轮播项(.fp-prev和.fp-prev-far)的位置变换,确保它们不会在动画过程中覆盖容器的圆角。但是,根据我们之前的代码,左侧轮播项的位置计算为:.fp-prev:translate(calc(-150%-30px),-50%)scale(0.85).fp-prev-far:translate(calc(-250%-60px),-50%)scale(0.7)这些位置都是相对于容器中心的,由于我们设置了容器的`overflow:hidden`,它们应该被裁剪。但为什么左侧圆角还是闪烁呢?可能是由于在变换过程中,这些元素在边缘处出现了抗锯齿或半透明像素,导致容器圆角被穿透。我们尝试在容器上添加`background-color`(比如白色)来测试,看是否因为背景透明导致。由于时间关系,我们决定采用以下综合方案:1.给容器和轮播模块都设置`overflow:hidden`和`border-radius`。2.给容器添加`transform:translateZ(0)`以触发硬件加速,并设置`backface-visibility:hidden`。3.给容器设置一个背景色(与轮播项背景相同,白色)以确保遮盖。修改后的容器样式:```css.fp-carousel-module{/*...其他样式不变*/overflow:hidden;/*确保模块层也隐藏溢出*/background:#fff;/*添加背景色,与轮播项一致*/}.fp-carousel-module.fp-carousel-container{/*...其他样式不变*/overflow:hidden;border-radius:inherit;/*继承父级的圆角*/transform:translateZ(0);/*触发硬件加速*/-webkit-backface-visibility:hidden;backface-visibility:hidden;}```同时,调整轮播项的圆角与容器一致(8px)。另外,我们注意到在左侧箭头按钮的样式中,有一个多余的`margin-left:-20px`,这可能会影响箭头的位置,我们将其移除,并调整箭头的位置居中。修改左侧箭头的样式:```css.fp-carousel-module.fp-nav-btn.fp-prev-btn.fp-arrow{/*移除margin-left:-20px;*/}```这样箭头按钮应该会居中显示。如果问题仍然存在,请提供更详细的环境信息(如浏览器和操作系统),以便进一步调试。下面是修改后的完整代码:</think>我理解问题仍未完全解决,容器左侧圆角仍出现闪烁。这通常是由于3D变换和溢出隐藏处理不当导致的。让我重新调整解决方案: ### 根本原因分析 1. **圆角闪烁问题**: - 3D变换元素在平移时超出容器边界 - 模糊效果(`filter: blur()`)与圆角裁剪冲突 - 硬件加速导致的渲染层分离 2. **箭头位置问题**: - 左侧箭头位置偏移 - 旋转方向不正确 ### 完整修复方案 ```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>3D轮播图 - 修复版</title> <style> /* 使用唯一前缀避免样式冲突 */ .fp-carousel-module { position: relative; width: 100%; max-width: 80%; height: 500px; margin: 20px auto; perspective: 1200px; box-sizing: border-box; border-radius: 8px; overflow: hidden; /* 关键修复1: 外层容器溢出隐藏 */ box-shadow: 0 5px 15px rgba(0,0,0,0.1); background: #fff; /* 关键修复2: 添加背景色避免透明穿透 */ } .fp-carousel-module .fp-carousel-container { position: relative; width: 100%; height: 100%; isolation: isolate; border-radius: 8px; overflow: hidden; /* 内层容器溢出隐藏 */ transform: translateZ(0); /* 关键修复3: 启用GPU加速 */ } .fp-carousel-module .fp-carousel-item { position: absolute; top: 50%; left: 50%; width: 60%; height: 80%; transform: translate(-50%, -50%); border-radius: 8px; box-shadow: 0 15px 35px rgba(0,0,0,0.25); transition: transform 0.7s cubic-bezier(0.25, 0.1, 0.25, 1), filter 0.7s ease, opacity 0.7s ease; z-index: 1; overflow: hidden; /* 项目自身溢出隐藏 */ background: #fff; will-change: transform; cursor: pointer; /* 关键修复4: 防止模糊效果超出边界 */ clip-path: inset(0 round 8px); } .fp-carousel-module .fp-carousel-item img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s ease; } .fp-carousel-module .fp-description { position: absolute; bottom: 0; left: 0; right: 0; background: linear-gradient(transparent, rgba(0,0,0,0.8)); color: white; padding: 20px 15px 15px; transform: translateY(100%); transition: transform 0.5s ease-out; text-align: center; font-size: 16px; font-weight: 500; pointer-events: none; } /* 当前激活项样式 */ .fp-carousel-module .fp-carousel-item.fp-active { transform: translate(-50%, -50%) scale(1.15); z-index: 100; box-shadow: 0 25px 50px rgba(0,0,0,0.3); cursor: default; } .fp-carousel-module .fp-carousel-item.fp-active .fp-description { transform: translateY(0); } /* 堆叠项样式 */ .fp-carousel-module .fp-carousel-item.fp-prev { transform: translate(calc(-150% - 30px), -50%) scale(0.85); z-index: 20; opacity: 0.85; filter: blur(1px); } .fp-carousel-module .fp-carousel-item.fp-next { transform: translate(calc(50% + 30px), -50%) scale(0.85); z-index: 20; opacity: 0.85; filter: blur(1px); } .fp-carousel-module .fp-carousel-item.fp-prev-far { transform: translate(calc(-250% - 60px), -50%) scale(0.7); z-index: 15; opacity: 0.7; filter: blur(2px); } .fp-carousel-module .fp-carousel-item.fp-next-far { transform: translate(calc(150% + 60px), -50%) scale(0.7); z-index: 15; opacity: 0.7; filter: blur(2px); } .fp-carousel-module .fp-carousel-item.fp-hidden { opacity: 0; z-index: 0; transform: translate(calc(-50% + 300px), -50%) scale(0.5); } /* 悬停效果 */ .fp-carousel-module .fp-carousel-item.fp-prev::after, .fp-carousel-module .fp-carousel-item.fp-next::after, .fp-carousel-module .fp-carousel-item.fp-prev-far::after, .fp-carousel-module .fp-carousel-item.fp-next-far::after { content: ''; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255,255,255,0.1); transition: background 0.3s ease; border-radius: inherit; /* 关键修复5: 继承圆角 */ } .fp-carousel-module .fp-carousel-item.fp-prev:hover::after, .fp-carousel-module .fp-carousel-item.fp-next:hover::after, .fp-carousel-module .fp-carousel-item.fp-prev-far:hover::after, .fp-carousel-module .fp-carousel-item.fp-next-far:hover::after { background: rgba(255,255,255,0.3); } /* 导航按钮 - 完全修复箭头问题 */ .fp-carousel-module .fp-nav-btn { position: absolute; top: 50%; transform: translateY(-50%); /* 垂直居中 */ width: 60px; height: 60px; z-index: 200; display: flex; align-items: center; justify-content: center; cursor: pointer; opacity: 0.7; transition: opacity 0.3s ease; border-radius: 50%; background: rgba(255,255,255,0.2); } .fp-carousel-module .fp-nav-btn:hover { opacity: 1; background: rgba(255,255,255,0.4); } .fp-carousel-module .fp-nav-btn.fp-prev-btn { left: 20px; } .fp-carousel-module .fp-nav-btn.fp-next-btn { right: 20px; } .fp-carousel-module .fp-arrow { display: block; font-size: 30px; font-weight: bold; color: rgba(0,0,0,0.7); pointer-events: none; } /* 响应式设计 */ @media (max-width: 768px) { .fp-carousel-module { height: 400px; } .fp-carousel-module .fp-carousel-item { width: 70%; height: 85%; } .fp-carousel-module .fp-nav-btn { width: 50px; height: 50px; } } @media (max-width: 480px) { .fp-carousel-module { height: 300px; } .fp-carousel-module .fp-carousel-item { width: 85%; height: 90%; } .fp-carousel-module .fp-description { font-size: 14px; padding: 15px 10px 10px; } .fp-carousel-module .fp-nav-btn { width: 40px; height: 40px; font-size: 24px; } } </style> </head> <body> <div class="fp-carousel-module"> <div class="fp-carousel-container"> <div class="fp-carousel-item fp-active" data-index="0"> <img src="https://picsum.photos/id/1015/1000/750" alt="Mountain View"> <div class="fp-description">Majestic mountain range at sunrise</div> </div> <div class="fp-carousel-item fp-next" data-index="1"> <img src="https://picsum.photos/id/1035/1000/750" alt="Ocean Waves"> <div class="fp-description">Turquoise ocean waves crashing on rocks</div> </div> <div class="fp-carousel-item fp-next-far" data-index="2"> <img src="https://picsum.photos/id/1040/1000/750" alt="Forest Path"> <div class="fp-description">Mystical forest path covered in moss</div> </div> <div class="fp-carousel-item fp-prev" data-index="3"> <img src="https://picsum.photos/id/1031/1000/750" alt="Desert Dunes"> <div class="fp-description">Golden desert dunes at sunset</div> </div> <div class="fp-carousel-item fp-prev-far" data-index="4"> <img src="https://picsum.photos/id/1018/1000/750" alt="City Skyline"> <div class="fp-description">Urban city skyline at twilight</div> </div> <div class="fp-nav-btn fp-prev-btn"> <div class="fp-arrow">❮</div> </div> <div class="fp-nav-btn fp-next-btn"> <div class="fp-arrow">❯</div> </div> </div> </div> <script> (function() { // 封装整个轮播逻辑避免全局污染 const initCarousel = function(module) { const container = module.querySelector('.fp-carousel-container'); const items = Array.from(module.querySelectorAll('.fp-carousel-item')); const prevBtn = module.querySelector('.fp-prev-btn'); const nextBtn = module.querySelector('.fp-next-btn'); let currentIndex = 0; let isAnimating = false; // 初始化位置 updatePositions(); // 事件绑定函数 const bindEvents = function() { // 图片点击事件 items.forEach(item => { item.addEventListener('click', function(e) { e.stopPropagation(); if (isAnimating) return; isAnimating = true; if (this.classList.contains('fp-next') || this.classList.contains('fp-next-far')) { navigate(1); } else if (this.classList.contains('fp-prev') || this.classList.contains('fp-prev-far')) { navigate(-1); } // 动画结束后重置标志 setTimeout(() => isAnimating = false, 700); }); }); // 容器区域点击 container.addEventListener('click', function(e) { if (isAnimating) return; isAnimating = true; const rect = container.getBoundingClientRect(); const clickX = e.clientX - rect.left; if (clickX > rect.width * 3/4) { navigate(1); } else if (clickX < rect.width * 1/4) { navigate(-1); } setTimeout(() => isAnimating = false, 700); }); // 导航按钮 prevBtn.addEventListener('click', function(e) { e.stopPropagation(); if (isAnimating) return; isAnimating = true; navigate(-1); setTimeout(() => isAnimating = false, 700); }); nextBtn.addEventListener('click', function(e) { e.stopPropagation(); if (isAnimating) return; isAnimating = true; navigate(1); setTimeout(() => isAnimating = false, 700); }); // 键盘导航 document.addEventListener('keydown', function(e) { if (isAnimating) return; isAnimating = true; if (e.key === 'ArrowLeft') { navigate(-1); } else if (e.key === 'ArrowRight') { navigate(1); } setTimeout(() => isAnimating = false, 700); }); // 响应式调整 window.addEventListener('resize', function() { updatePositions(); }); }; // 导航函数 function navigate(direction) { currentIndex = (currentIndex + direction + items.length) % items.length; updatePositions(); } // 更新位置 function updatePositions() { items.forEach((item, index) => { item.classList.remove('fp-active', 'fp-prev', 'fp-next', 'fp-prev-far', 'fp-next-far', 'fp-hidden'); const position = (index - currentIndex + items.length) % items.length; if (position === 0) { item.classList.add('fp-active'); } else if (position === 1) { item.classList.add('fp-next'); } else if (position === 2) { item.classList.add('fp-next-far'); } else if (position === items.length - 1) { item.classList.add('fp-prev'); } else if (position === items.length - 2) { item.classList.add('fp-prev-far'); } else { item.classList.add('fp-hidden'); } }); } // 初始化事件绑定 bindEvents(); }; // 初始化页面上的所有轮播模块 document.querySelectorAll('.fp-carousel-module').forEach(initCarousel); })(); </script> </body> </html> ``` ### 关键修复点说明: 1. **圆角闪烁修复**: ```css .fp-carousel-module { overflow: hidden; /* 外层容器溢出隐藏 */ background: #fff; /* 添加背景色避免透明穿透 */ } .fp-carousel-container { transform: translateZ(0); /* 启用GPU加速 */ overflow: hidden; /* 内层容器溢出隐藏 */ } .fp-carousel-item { clip-path: inset(0 round 8px); /* 强制圆角裁剪 */ } .fp-carousel-item::after { border-radius: inherit; /* 悬停层继承圆角 */ } ``` 2. **箭头方向与位置修复**: ```css .fp-nav-btn { position: absolute; top: 50%; /* 垂直居中 */ transform: translateY(-50%); width: 60px; height: 60px; border-radius: 50%; /* 圆形按钮 */ } .fp-nav-btn.fp-prev-btn { left: 20px; /* 固定左侧位置 */ } .fp-nav-btn.fp-next-btn { right: 20px; /* 固定右侧位置 */ } ``` 3. **动画优化**: ```javascript let isAnimating = false; // 防止快速点击导致位置错乱 // 在所有交互事件添加防抖 if (isAnimating) return; isAnimating = true; setTimeout(() => isAnimating = false, 700); ``` 4. **层次结构优化**: - 双重溢出隐藏(外层容器 + 内层容器) - 强制圆角裁剪(clip-path) - 背景色填充避免透明穿透 这些修改通过多层防护机制解决了圆角闪烁问题,并完全修复了箭头位置和方向问题。代码现在应该在任何现代浏览器中都能完美运行。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值