You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

垂直全屏Swiper滚动冲突:如何禁用未滚完时的滑屏切换?

解决垂直全屏Swiper的两个核心问题

问题1:Slide内滚动与Swiper滑屏切换冲突

当slide内容溢出开启滚动后,滚动内部内容时会误触发Swiper的滑屏切换。解决逻辑是:仅当slide滚动到顶部/底部边缘时,才允许Swiper触发滑屏切换。

实现步骤:

  1. 给Swiper组件添加ref,用于获取实例进行状态控制
  2. 给可滚动的slide绑定滚动事件,实时判断滚动位置
  3. 根据滚动位置动态启用/禁用Swiper的鼠标滚轮和触摸滑动功能

修改后的MainSlider.js代码:

import { useEffect, useRef } from 'react';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
import 'swiper/css/pagination';
import { Mousewheel, Pagination } from 'swiper/modules';

const MainSlider = () => {
  const swiperRef = useRef(null);
  const slideRefs = useRef([]);

  // 处理slide滚动事件
  const handleSlideScroll = (e) => {
    const slide = e.target;
    const isAtTop = slide.scrollTop === 0;
    const isAtBottom = slide.scrollTop + slide.clientHeight >= slide.scrollHeight;
    const swiper = swiperRef.current?.swiper;

    if (swiper) {
      // 只有滚动到边缘时,才允许Swiper的滑屏和滚轮控制
      swiper.mousewheel.enable(isAtTop || isAtBottom);
      swiper.touchEventsEnabled = isAtTop || isAtBottom;
    }
  };

  useEffect(() => {
    // 给所有可滚动的slide绑定滚动事件
    slideRefs.current.forEach(ref => {
      if (ref) {
        ref.addEventListener('scroll', handleSlideScroll);
      }
    });

    return () => {
      // 清理事件监听
      slideRefs.current.forEach(ref => {
        if (ref) {
          ref.removeEventListener('scroll', handleSlideScroll);
        }
      });
    };
  }, []);

  return (
    <Swiper
      ref={swiperRef}
      className={styles.swiper}
      direction="vertical"
      slidesPerView="auto"
      spaceBetween={0}
      mousewheel={true}
      speed={700}
      touchReleaseOnEdges={true}
      threshold={20}
      pagination={{
        clickable: true,
      }}
      modules={[Mousewheel, Pagination]}
    >
      <SwiperSlide className={styles.slide} ref={el => slideRefs.current[0] = el}>
        <SectionOne/>
      </SwiperSlide>
      <SwiperSlide className={styles.slide} ref={el => slideRefs.current[1] = el}>
        <AnswersTwo/>
      </SwiperSlide>
    </Swiper>
  );
};

export default MainSlider;

问题2:移动端模式切换后滑屏功能需刷新才生效

窗口尺寸切换到移动端模式时,Swiper没有自动更新布局和状态,导致滑屏功能失效。解决逻辑是:监听窗口resize事件,触发Swiper实例的update方法,同时重新调整滚动控制逻辑。

实现步骤:

在原有的useEffect中添加resize事件监听,更新Swiper实例并重置滚动状态:

修改MainSlider.js中的useEffect:

useEffect(() => {
  // 绑定slide滚动事件
  const bindScrollEvents = () => {
    slideRefs.current.forEach(ref => {
      if (ref) {
        ref.removeEventListener('scroll', handleSlideScroll);
        ref.addEventListener('scroll', handleSlideScroll);
        // 初始化时判断一次滚动位置
        handleSlideScroll({ target: ref });
      }
    });
  };

  bindScrollEvents();

  // 监听窗口resize事件
  const handleResize = () => {
    const swiper = swiperRef.current?.swiper;
    if (swiper) {
      swiper.update(); // 更新Swiper布局
      bindScrollEvents(); // 重新绑定滚动事件并初始化状态
    }
  };

  window.addEventListener('resize', handleResize);

  return () => {
    window.removeEventListener('resize', handleResize);
    slideRefs.current.forEach(ref => {
      if (ref) {
        ref.removeEventListener('scroll', handleSlideScroll);
      }
    });
  };
}, []);

同时优化SCSS中的滚动样式,避免干扰:

.swiper {
  width: 100%;
  height: 100vh;
}

.slide {
  min-height: 100vh;
  text-align: center;
  font-size: 18px;
  background: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  margin: auto;
  overflow: hidden;
  @media only screen and (max-width: 1023px) {
    flex-wrap: wrap;
    overflow-y: scroll; // 明确垂直滚动,避免横向滚动干扰
    -webkit-overflow-scrolling: touch; // 优化移动端滚动手感
  }
}

内容的提问来源于stack exchange,提问作者wannnwdooo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 09:50:42