如何实现动态生成div的独立Swipe交互,解决全局响应问题
解决动态生成元素的独立滑动响应问题
你的问题核心很明确:当前代码里用全局选择器$('.option1')会选中页面上所有同类元素,所以滑动一个swipeArea会影响全部。和你之前用$(this)实现独立响应的思路一样,我们只需要把操作范围限定在当前触发滑动的swipeArea内部即可。
具体修改步骤:
- 保留当前元素的引用:在循环绑定事件时,用闭包保存当前
swipeArea的引用(避免循环变量共享导致的元素混淆问题)。 - 限定选择器范围:在滑动回调里,只查找当前
swipeArea内部的.option1和.option2,而不是全局查找。
修改后的完整JavaScript代码:
var el = document.getElementsByClassName('swipeArea'); for (var i = 0; i < el.length; i++) { // 用立即执行函数创建闭包,固定当前的swipeArea元素 (function(currentSwipeArea) { swipedetect(currentSwipeArea, function(swipedir) { // 只在当前滑动区域内查找选项元素 var $option1 = $(currentSwipeArea).find('.option1'); var $option2 = $(currentSwipeArea).find('.option2'); if (swipedir == 'up') { $option1.css('display', 'block'); $option2.css('display', 'none'); } else if (swipedir == 'down') { $option1.css('display', 'none'); $option2.css('display', 'block'); } else { $option1.css('display', 'none'); $option2.css('display', 'none'); } }); })(el[i]); } // 你的swipedetect函数保持不变 function swipedetect(el, callback){ var touchsurface = el, swipedir, startX, startY, distX, distY, threshold = 150, //required min distance traveled to be considered swipe restraint = 100, // maximum distance allowed at the same time in perpendicular direction allowedTime = 300, // maximum time allowed to travel that distance elapsedTime, startTime, handleswipe = callback || function(swipedir){} touchsurface.addEventListener('touchstart', function(e){ var touchobj = e.changedTouches[0] swipedir = 'none' dist = 0 startX = touchobj.pageX startY = touchobj.pageY startTime = new Date().getTime() // record time when finger first makes contact with surface e.preventDefault() }, false) touchsurface.addEventListener('touchmove', function(e){ e.preventDefault() // prevent scrolling when inside DIV }, false) touchsurface.addEventListener('touchend', function(e){ var touchobj = e.changedTouches[0] distX = touchobj.pageX - startX // get horizontal dist traveled by finger while in contact with surface distY = touchobj.pageY - startY // get vertical dist traveled by finger while in contact with surface elapsedTime = new Date().getTime() - startTime // get time elapsed if (elapsedTime <= allowedTime){ // first condition for swipe met if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint){ // 2nd condition for vertical swipe met swipedir = (distY < 0)? 'up' : 'down' // if dist traveled is negative, it indicates up swipe } } handleswipe(swipedir) e.preventDefault() }, false) }
为什么这样修改有效?
- 闭包的作用:循环中用立即执行函数把当前的
el[i]赋值给currentSwipeArea,确保每个滑动回调都能拿到自己对应的swipeArea元素,不会因为循环变量i的更新而混淆。 - 范围限定的选择器:
$(currentSwipeArea).find('.option1')只会查找当前滑动区域内部的选项元素,不会影响其他动态生成的swipeArea里的内容,和你之前用$(this)实现独立响应的逻辑完全一致。
额外优化建议(可选):
- 可以把
css('display', ...)换成jQuery的show()和hide()方法,写法更简洁:比如$option1.show(); $option2.hide(); - 如果你的项目支持ES6+,可以用
let代替var来声明循环变量,这样可以省去闭包:for (let i = 0; i < el.length; i++) { let currentSwipeArea = el[i]; swipedetect(currentSwipeArea, function(swipedir) { // 后续逻辑和上面一致 }); }
内容的提问来源于stack exchange,提问作者mark n
相关产品推荐
相关产品推荐

