React swiper加载大量数据优化(无限自动轮播)

1,078 阅读1分钟

场景

需要在一个swiper加载将近500个动态canvas,并且要自动轮播。

解决方案:

方案一:只加载显示的几个item,看不见的只加载 简单的item。(因为加载的动态的canvas重复的加载卸载组件也会 非常卡顿,所以这个方法不合适)

const setSwiperSlide = (e: any) => {
    // console.log('realIndex', e.realIndex);
    setMarkNum(e.realIndex);
  };
  
<Swiper spaceBetween={0} slidesPerView={3} onSlideChange={setSwiperSlide} autoplay={{ disableOnInteraction: false, delay: 6000 }}>
          {classData.length > 0 &&
            classData.map((item: IClassData, index: number) => {
              if ([markNum - 1, markNum, markNum + 1, markNum + 2, markNum + 3].includes(index)) {
                return (
                  <SwiperSlide key={index}>
                    <div className={style.liquidFill} id="liquidFill1">
                      <WaveGlobe
                        rate={(item.ATTENDANCE_COUNT / item.PEOPLE_TOTAL).toFixed(2)}
                        course={item.COURSE_NAME}
                        rateString={item.ATTENDANCE_RATE}
                      ></WaveGlobe>
                    </div>
                  </SwiperSlide>
                );
              } else {
                return <SwiperSlide key={index}></SwiperSlide>;
              }
            })}
        </Swiper>

方案二:只用5个item去循环显示,然后动态的更新数据。

(用5个item是因为中间要显示3个,所以要多一个记录前一个的数据,一个记录后面的数据。)

    const swiperItems = [0, 1, 2, 3, 4];
    // 滑块向前滑动后
  const SlidePrevTransitionEnd = (e: any) => {
    if (prevMarkNum - 1 < 0) {
      mySwiper.current.firstChild.swiper.slideToLoop(2, 0, false);
      return;
    }
    if (e.realIndex == 3) {
      chartData[2] = courseAttendance[prevMarkNum - 1];
    } else if (e.realIndex == 4) {
      chartData[3] = courseAttendance[prevMarkNum - 1];
    } else if (e.realIndex == 0) {
      chartData[4] = courseAttendance[prevMarkNum - 1];
    } else if (e.realIndex == 1) {
      chartData[0] = courseAttendance[prevMarkNum - 1];
    } else if (e.realIndex == 2) {
      chartData[1] = courseAttendance[prevMarkNum - 1];
    }
    setMarkNum((e) => e - 1);
    setPrevMarkNum((e) => e - 1);
  };
  // 滑块向后滑动后
  const SlideNextTransitionEnd = (e: any) => {
    if (markNum == courseAttendance.length - 1) {
      setMarkNum(0);
      setPrevMarkNum(-1);
    }
    if (e.realIndex == 3) {
      chartData[1] = courseAttendance[markNum];
      chartData[2] = courseAttendance[prevMarkNum + 1];
    } else if (e.realIndex == 4) {
      chartData[2] = courseAttendance[markNum];
      chartData[3] = courseAttendance[prevMarkNum + 1];
    } else if (e.realIndex == 0) {
      chartData[3] = courseAttendance[markNum];
      chartData[4] = courseAttendance[prevMarkNum + 1];
    } else if (e.realIndex == 1) {
      chartData[4] = courseAttendance[markNum];
      chartData[0] = courseAttendance[prevMarkNum + 1];
    } else if (e.realIndex == 2) {
      chartData[0] = courseAttendance[markNum];
      chartData[1] = courseAttendance[prevMarkNum + 1];
    }
    setChartData(chartData);
    setMarkNum((e) => e + 1);
    setPrevMarkNum((e) => e + 1);
  };
    
    <Swiper
          loop
          spaceBetween={0}
          slidesPerView={3}
          onSlidePrevTransitionEnd={SlidePrevTransitionEnd}
          onSlideNextTransitionEnd={SlideNextTransitionEnd}
          autoplay={{ disableOnInteraction: false, delay: 5000 }}
        >
          {chartData.length > 0 &&
            swiperItems.map((item: any, index: number) => {
              return (
                <SwiperSlide key={index}>
                  <div className={style.liquidFill} id="liquidFill1">
                    <WaveGlobe
                      rate={(chartData[index].ATTENDANCE_COUNT / chartData[index].PEOPLE_TOTAL).toFixed(2)}
                      course={chartData[index].COURSE_NAME}
                      rateString={chartData[index].ATTENDANCE_RATE}
                    ></WaveGlobe>
                  </div>
                </SwiperSlide>
              );
            })}
        </Swiper>

缺点:一下滑动只能滑过一个item,要是划过两个会导致数据混乱,所以必要可以限制滑动的距离。

性能提升:cpu占用50% => cpu占用30%,提升20%多的性能。

image.png image.png

image.png image.png