如何在JavaScript或Vue中检测跨元素的触摸滑动(触摸进入)?
Vue移动端滑动触发多组件触摸事件解决方案
你遇到的问题是浏览器原生触摸事件的机制导致的:touchmove事件只会绑定在首次触发触摸的元素上,滑动过程中即使经过其他元素,也不会自动触发这些元素的touchmove事件,所以直接给每个<someComponent>绑定事件是无效的。
要实现滑动时模拟hover的tooltip效果,确实需要通过全局(或父容器)绑定触摸事件,然后实时检测手指下方的元素,具体实现步骤如下:
核心思路
- 在父容器(或
document)上绑定touchstart、touchmove、touchend三个事件 - 在
touchmove中获取触摸点的坐标,用document.elementFromPoint()获取当前触摸位置的DOM元素 - 判断该元素是否是目标组件,若是则触发tooltip逻辑,同时避免重复触发同一组件
Vue示例代码
<template> <!-- 父容器绑定触摸事件 --> <div class="sentence-wrapper" @touchstart="onTouchStart" @touchmove="onTouchMove" @touchend="onTouchEnd"> <!-- 给每个组件添加标识类名和自定义属性 --> <someComponent v-for="(word, id) in sentence" :key="id" :data-component-id="id" class="touch-target-component"> </someComponent> </div> </template> <script> export default { data() { return { sentence: ['组件1', '组件2', '组件3'], activeComponentId: null // 记录当前激活的组件ID,避免重复触发 } }, methods: { onTouchStart(e) { // 触摸开始时,检测初始触摸的组件 const touch = e.touches[0] const target = document.elementFromPoint(touch.clientX, touch.clientY) this.checkAndTriggerTarget(target) }, onTouchMove(e) { // 滑动过程中实时检测触摸位置的组件 const touch = e.touches[0] const target = document.elementFromPoint(touch.clientX, touch.clientY) this.checkAndTriggerTarget(target) }, onTouchEnd() { // 触摸结束后重置激活状态 this.activeComponentId = null // 这里可以添加隐藏tooltip的逻辑 }, checkAndTriggerTarget(target) { // 判断是否是目标组件,且未重复触发 if (!target?.classList.contains('touch-target-component')) return const componentId = target.dataset.componentId if (componentId !== this.activeComponentId) { this.activeComponentId = componentId this.showTooltip(componentId) // 触发tooltip显示逻辑 } }, showTooltip(componentId) { // 根据组件ID处理tooltip显示,比如找到对应组件实例、展示对应内容 console.log(`显示组件${componentId}的tooltip`) } } } </script> <style scoped> .sentence-wrapper { /* 确保父容器占满可触摸区域,避免触摸事件失效 */ width: 100%; min-height: 100vh; } .touch-target-component { /* 给组件添加必要的样式,确保可被elementFromPoint检测到 */ display: inline-block; padding: 8px; } </style>
注意事项
document.elementFromPoint()会返回坐标点最上层的DOM元素,所以要确保目标组件的层级不会被其他元素遮挡- 如果页面需要滚动,不要随意在触摸事件中调用
e.preventDefault(),否则会阻止页面滚动;若必须阻止,需单独处理滚动逻辑 - 可以用Vue的
ref替代data-*属性来标识组件,但data-*属性在DOM检测时更直接
总结:这种滑动触发多组件的场景,确实无法通过给单个组件绑定touchmove实现,必须通过全局/父容器监听触摸事件,再检测坐标下的元素来模拟hover效果。
内容的提问来源于stack exchange,提问作者Gazzer
相关产品推荐
相关产品推荐

