uni-app swiper 设置 vertical 为 false 时,应该只响应左右滑动的手势

uni-app swiper 设置 vertical 为 false 时,应该只响应左右滑动的手势

开发环境 版本号 项目创建方式
Windows macOS Big Sur 11.2.3 HBuilderX

操作步骤:

  • swiper 默认应该只响应左右滑动的手势

预期结果:

  • swiper 设置 vertical 为 false 时,应该只响应左右滑动的手势
  • swiper 设置 vertical 为 true 时,应该只响应上下滑动的手势

实际结果:

  • swiper 没有任何手势控制

bug描述:

  • swiper 设置 vertical 为 false 时,应该只响应左右滑动的手势
  • swiper 设置 vertical 为 true 时,应该只响应上下滑动的手势
  • 目前,配置成横向的时候,实际测试发现会响应上下滑动手势
  • 对于 swiper-list 这种结构,会导致上下滑动时候,左右也会滑动
  • 如果 swiper 在左右滑动的时候,会导致内部的list也在做滑动,体验很不好

更多关于uni-app swiper 设置 vertical 为 false 时,应该只响应左右滑动的手势的实战教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

测试了,下安卓和ios,swiper-list 结构,在 3.2.3 版本里面没有这么明显滑动差异

更多关于uni-app swiper 设置 vertical 为 false 时,应该只响应左右滑动的手势的实战教程也可以访问 https://www.itying.com/category-93-b0.html


根据你的描述,这确实是 uni-app 中 swiper 组件一个已知的交互问题。核心原因在于 swiper 组件(尤其在App端和部分小程序平台)的默认手势识别策略可能不够严格,没有将垂直滑动和水平滑动事件完全隔离。

vertical="false"(即横向模式)时,一个轻微的垂直方向手势分量也可能被误判为有效的滑动意图,从而触发翻页。这在与内部可垂直滚动的组件(如 scroll-view 或列表)嵌套时,体验冲突尤为明显。

直接的解决方案是使用 @touch 事件手动控制:

你可以通过捕获触摸事件,计算滑动的方向,并在非目标方向上阻止 swiper 的默认行为。

<template>
  <swiper
    :vertical="false"
    @touchstart="handleTouchStart"
    @touchmove="handleTouchMove"
    @touchend="handleTouchEnd"
  >
    <!-- swiper-item 内容 -->
  </swiper>
</template>

<script>
export default {
  data() {
    return {
      startX: 0,
      startY: 0,
      isHorizontal: false // 标记当前是否为有效横向滑动
    };
  },
  methods: {
    handleTouchStart(e) {
      this.startX = e.touches[0].clientX;
      this.startY = e.touches[0].clientY;
      this.isHorizontal = false;
    },
    handleTouchMove(e) {
      if (this.isHorizontal) return; // 如果是横向滑动,则允许后续移动事件

      const moveX = e.touches[0].clientX - this.startX;
      const moveY = e.touches[0].clientY - this.startY;

      // 计算滑动角度,如果更偏向垂直方向,则阻止事件(可根据需要调整阈值)
      if (Math.abs(moveY) > Math.abs(moveX) * 1.5) { // 阈值示例
        // 阻止 swiper 对此次滑动的响应,让内部列表滚动
        // 注意:uni-app中无法直接e.preventDefault(),但可通过返回或标记来逻辑控制
        this.isHorizontal = false;
        // 如果需要,可以在这里通知子组件允许滚动
      } else {
        this.isHorizontal = true; // 标记为横向滑动,允许swiper翻页
      }
    },
    handleTouchEnd() {
      this.isHorizontal = false;
    }
  }
};
</script>
回到顶部