在Vue中使用swiper触摸屏滑动切换会导致路由切换

Vue中使用swiper的过程中,使用的是swiper卡片化轮播,由于要做成网站 所以项目在浏览器中使用 使用过程中鼠标可以对卡片化轮播进行滑动切换,但是使用触摸屏的话却不能对卡片化轮播进行滑动切换,左右滑动的时候会导致路由变化,请问各位有什么方式可以解决嘛(需要触摸屏滑动切换不能禁用掉触摸滑动切换)

你好,可以通过swiper的参数touchMoveStopPropagation来解决该问题。该参数默认值为false,即当触摸跟随滑动时也会触发touchmove事件,会影响到浏览器的默认行为(即滚动页面),从而导致路由变化等问题。将该参数设置为true时,可以阻止这种行为,从而实现触摸屏下的卡片化轮播。

具体实现方式为,在swiper的初始化参数中添加touchMoveStopPropagation: true参数即可,例如:

new Swiper('.swiper-container', {
  touchMoveStopPropagation: true,
  ...
});

另外,还可以通过preventDefault的方式禁止浏览器的默认行为,避免路由变化等问题,例如:

document.querySelector('.swiper-container').addEventListener('touchmove', function (e) { 
  e.preventDefault(); 
});

希望能够帮助你解决问题。创作不易,如果有用记得给个采纳哈 <<<<<<<<<<撒花>>>>>>>>

  • 这篇博客: vue中使用swiper页面不滑动,swiper中的js不生效的问题解决中的 2 、安装方法 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • // 使用指令安装
    npm i swiper@3.4.2 -S
    
  • 以下回答由chatgpt基于相关博客总结生成:

    根据参考资料中的代码以及描述,可以得出以下解决方案:

    1. 在使用Swiper时,应该设置禁止路由切换:
    var swiper = new Swiper('.swiper-container', {
      on: {
        slideChangeTransitionEnd: function(){
          Vue.$router.replace({path: '/xxx/' + this.activeIndex});
        }
      }
    })
    
    1. 为了在移动端让Swiper能够响应滑动事件,我们需要为Swiper容器添加touchstart和touchmove事件,并判断是否应该阻止事件冒泡:
    var swiperContainer = document.querySelector('.swiper-container');
    var startTouchY;
    var endTouchY;
    
    swiperContainer.addEventListener('touchstart', function(evt) {
      // 记录当前触摸位置的Y坐标
      startTouchY = evt.touches[0].pageY;
      // 当前滚动容器的scrollTop值
      var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
      // 该元素的scrollTop值
      var elementScrollTop = this.scrollTop;
      // 判断是否允许滚动冒泡的条件
      // 1. 容器有滚动条
      // 2. 触摸坐标在容器顶部,且往上滑动
      // 3. 触摸坐标在容器底部,且往下滑动
      var allowScrollBubble = 
        elementScrollTop === 0 && scrollTop < 5 || 
        elementScrollTop + this.offsetHeight >= this.scrollHeight && scrollTop > startTouchY;
      if (!allowScrollBubble) {
        evt.stopPropagation();
      }
    });
    
    swiperContainer.addEventListener('touchmove', function(evt) {
      // 判断是否允许滚动冒泡的条件
      // 1. 允许Y轴滑动
      // 2. 容器有滚动条
      var allowScrollBubble = 
        Math.abs(evt.touches[0].screenY - startTouchY) > Math.abs(evt.touches[0].screenX - startX) &&
        this.offsetHeight < this.scrollHeight;
    
      if (!allowScrollBubble) {
        evt.stopPropagation();
        evt.preventDefault();
      }
    
      // 记录滑动结束位置的Y坐标
      endTouchY = evt.touches[0].pageY;
    });
    

    上面的代码会判断当前的触摸事件是否在Swiper容器的顶部或底部区域产生,只有这两个区域在滚动或往上下滑动时才会进行冒泡。要注意的是,在处理touchmove事件时,需要调用preventDefault方法以防止默认的滑动行为。

    1. 如果你的页面中有多个Swiper组件嵌套,可以使用类似下面的代码来判断当前是否处于需要滚动的Swiper容器内:
    swiperContainer.addEventListener('touchstart', function(evt) {
      var node = evt.target;
      while (node !== swiperContainer) {
        if (node.classList.contains('swiper-slide')) {
          isAllowScroll = true;
          break;
        }
        node = node.parentNode;
      }
    });
    swiperContainer.addEventListener('touchmove', function(evt) {
      // 判断是否允许滚动冒泡的条件
      var allowScrollBubble = 
        Math.abs(evt.touches[0].screenY - startTouchY) > Math.abs(evt.touches[0].screenX - startX) &&
        this.offsetHeight < this.scrollHeight &&
        isAllowScroll;
    
      if (!allowScrollBubble) {
        evt.stopPropagation();
        evt.preventDefault();
      }
    
      // 记录滑动结束位置的Y坐标
      endTouchY = evt.touches[0].pageY;
    });
    
    1. 如果你需要在Swiper组件中嵌入Vue组件,可以在touchstart事件中调用Vue实例的$emit方法来通知子组件已经开始滑动:
    swiperContainer.addEventListener('touchstart', function(evt) {
      Vue.$emit('swiper:start', {});
    });
    

    然后在Vue组件中,可以在created方法中监听该事件:

    export default {
      props: {
        index: Number
      },
      created() {
        Vue.$on('swiper:start', () => {
          this.$nextTick(() => {
            this.$refs.innerSwiper.swiper.slideTo(this.index, 0);
          });
        });
      }
    };
    

    这里我们在子组件内监听swiper:start事件,并利用refs属性获取到内部的Swiper实例,然后通过该实例的slideTo方法来跳转到指定的slide。

    应该注意的是,这种方式在Swiper组件处于隐藏状态时是不起作用的,因为所有子组件在父元素隐藏时都是不会挂载的。