微信小程序实现swiper无限滚动和预加载

Blank
2025-08-31 / 0 评论 / 14 阅读 / 正在检测是否收录...

月份卡片无限滚动和预加载示例,只要 list 长度=3,swiper 的 circular 就能做出无限滑动的错觉;再配合月份数组的整体左移/右移,让视觉与数据始终保持同步

meznl2d2.png

swiper 注意开启循环 circular,默认停在中间卡片 current="{{1}}"

右滑实现原理,左滑同样的,通过判断swiper下标调整list位置即可

meznt2sl.png

<swiper class="swiper" circular indicator-dots current="{{1}}" bindanimationfinish="onSwiperFinish">
  <swiper-item wx:for="{{list}}" wx:key="id">
    <view class="page" style="background: {{item.color}}">
      <view class="txt">{{item.title}}</view>
      <view class="txt">当前月 - {{timelist[swiper_index]}}</view>
    </view>
  </swiper-item>
</swiper>
Page({
  data: {
    list: [{
        id: 1,
        title: '页面 1',
        color: '#ff7675'
      },
      {
        id: 2,
        title: '页面 2',
        color: '#74b9ff'
      },
      {
        id: 3,
        title: '页面 3',
        color: '#55efc4'
      }
    ],
    swiper_index: 1, //当前滑动下标
    swiper_diff: 0, //滑动操作,1右滑,0左滑
    last_swiper_index: 1, //上一个滑动下标
    timelist: []
  },

  async onLoad() {
    this.IniDate();
  },

  // 初始化日期数据
  async IniDate(date = new Date()) {
    console.log("开始初始化时间...");
    const year = date.getFullYear();
    const month = (date.getMonth() + 1).toString().padStart(2, '0');
    const day = date.getDate().toString().padStart(2, '0');
    const currentDate = `${year}/${month}/${day}`;
    this.setData({
      now_date: currentDate,
      now_date_: `${year}-${month}-${day}`,
      now_Year: year,
      now_Month: month,
    });
    console.log("时间初始化完成~");

    const timeArr = this.data.now_date.split('/');
    const currentMonth = timeArr[1].padStart(2, '0');
    const currentYear = timeArr[0];
    let searchMonthList = [`${currentYear}-${currentMonth}`];

    // 计算前后月份
    if (Number(currentMonth) > 1 && Number(currentMonth) < 12) {
      const preMonth = (Number(currentMonth) - 1).toString().padStart(2, '0');
      const nextMonth = (Number(currentMonth) + 1).toString().padStart(2, '0');
      searchMonthList = [`${currentYear}-${preMonth}`, searchMonthList[0], `${currentYear}-${nextMonth}`];
    } else if (Number(currentMonth) === 1) {
      const preYear = Number(currentYear) - 1;
      searchMonthList = [`${preYear}-12`, searchMonthList[0], `${currentYear}-02`];
    } else if (Number(currentMonth) === 12) {
      const nextYear = Number(currentYear) + 1;
      searchMonthList = [`${currentYear}-11`, searchMonthList[0], `${nextYear}-01`];
    }

    // 处理日历列表展示顺序
    const index = this.data.swiper_index;
    const diff = this.data.swiper_diff;
    let allList = [];
    const list = searchMonthList;
    // 右滑处理
    if (diff == 1) {
      if (index === 0) {
        allList = [list[1], list[2], list[0]];
      } else if (index === 1) {
        allList = [list[0], list[1], list[2]];
      } else if (index === 2) {
        allList = [list[2], list[0], list[1]];
      }
    } else {
      // 左滑处理
      if (index === 1) {
        allList = [list[0], list[1], list[2]];
      } else if (index === 0) {
        allList = [list[1], list[2], list[0]];
      } else if (index === 2) {
        allList = [list[2], list[0], list[1]];
      }
    }
    console.log(diff, index, allList)
    this.setData({
      timelist: allList
    });
  },

  // 用户滑动swiper
  onSwiperFinish(e) {
    const swiper_index = e.detail.current;
    const last_swiper_index = this.data.last_swiper_index
    const diff = swiper_index - last_swiper_index;
    // 判断滑动方向 1,-2 右滑, -1,2 左滑
    if (diff === 1 || diff === -2) {
      this.setData({
        swiper_diff: 1
      })
      console.log("右滑");
      this.nextMonth();
    } else if (diff === -1 || diff === 2) {
      this.setData({
        swiper_diff: 0
      })
      console.log("左滑");
      this.prevMonth();
    }
    this.setData({
      swiper_index: swiper_index,
      last_swiper_index: swiper_index
    })
  },

  // 切换到上个月
  async prevMonth() {
    const date = new Date(this.data.now_date);
    const prev = await this.prevMonth_date(date);
    console.log(prev)
    this.IniDate(prev, true);
  },

  // 切换到下个月
  async nextMonth() {
    const date = new Date(this.data.now_date);
    const next = await this.nextMonth_date(date);
    console.log(next)
    this.IniDate(next, true);
  },

  nextMonth_date(date) {
    const d = new Date(date); // 克隆
    const dayOfMonth = d.getDate();
    d.setDate(1); // 先挪到 1 号,避免 31→3 月 3 日
    d.setMonth(d.getMonth() + 1);
    const lastDay = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
    d.setDate(Math.min(dayOfMonth, lastDay)); // 取较小值防止溢出
    return d;
  },

  prevMonth_date(date) {
    const d = new Date(date); // 克隆
    const dayOfMonth = d.getDate();
    d.setDate(1); // 先挪到 1 号,避免 31→3 月 3 日
    d.setMonth(d.getMonth() - 1);
    const lastDay = new Date(d.getFullYear(), d.getMonth() + 1, 0).getDate();
    d.setDate(Math.min(dayOfMonth, lastDay)); // 取较小值防止溢出
    return d;
  },

});
/* pages/index/index.wxss */
.wrap {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.swiper {
  margin-top: 200rpx;
  width: 90%;
  height: 500rpx;
  margin-left: 5%;
  border-radius: 10rpx;
}

.page {
  border-radius: 10rpx;
  padding: 10rpx;
  height: 500rpx;
  font-size: 40rpx;
}

.txt {
  margin-top: 100rpx;
  text-align: center;
  color: #fff;
  font-size: 40rpx;
  width: 100%;
  height: 100rpx;
}
0

评论 (0)

夸夸
取消