更新记录

1.0.0(2024-11-12)

feat: virtual-swiper init


平台兼容性

Vue2 Vue3
App 快应用 微信小程序 支付宝小程序 百度小程序 字节小程序 QQ小程序
× × × × ×
钉钉小程序 快手小程序 飞书小程序 京东小程序
× × × ×
H5-Safari Android Browser 微信浏览器(Android) QQ浏览器(Android) Chrome IE Edge Firefox PC-Safari
× × × × × × × × ×

useVirtualSwiper Hook

当在微信小程序中,遇到一个页面下需要一次性渲染 swiper-item 导致页面卡顿,DOM 节点爆炸的情况,可以使用此 hook 优化 swiper-item 的渲染。

思路

一次性只渲染 3 个 swiper-item,分别是当前项、前一项、后一项。在 swiper-view change 事件后,根据滑动方向确定当前渲染的数据项,然后获取对应的渲染数据集,并根据 swiper-view 当前的 current 对数据集进行偏移,从而达到数据集与 current 可以对应,避免 swiper-view 发生渲染抖动。

使用

使用 VirtualSwiper 组件

只需要通过作用域插槽 swiper-item 渲染 swiper-item 的内容。

<template>
  <virtual-swiper
    v-if="initFlag"
    :circular="circular"
    :duration="100"
    :data="dataSource"
    class="swiper"
  >
    <template #swiper-item="{ item }">
      <view
        class="swiper-item uni-bg-red"
        :style="{ color: `rgba(${2 * item.id}, 123, ${1 * item.id})` }"
      >
        <text>{{ item.id }}</text>
        <view
          :style="{
            display: 'inline-block',
            width: '100rpx',
            height: '100rpx',
            backgroundColor: `rgba(${2 * item.id}, 123, ${1 * item.id})`,
          }"
        ></view>
      </view>
    </template>
  </virtual-swiper>
</template>

<script setup>
import { onMounted, ref } from 'vue';

const circular = ref(false);
const initFlag = ref(false);
const dataSource = ref([]);

onMounted(() => {
  for (let i = 0; i < 111; i++) {
    dataSource.value.push(i);
  }
  console.log('>>>data', dataSource.value);
  initFlag.value = true;
});
</script>

<style lang="scss">
.swiper {
  position: relative;
  box-sizing: border-box;
  display: block;
  height: 300px;
}

.swiper .swiper-item {
  display: block;
  height: 300px;
  line-height: 300px;
  text-align: center;
  background: #f8f8f9;
}
</style>

如果swiper绑定数据是异步数据,建议通过v-if进行控制在首次请求完后才渲染swiper;或者在异步结束后手动通过组件实例引用手动调用 scrollIntoSwiper 进行首次定位swiper-item。

使用内置 hook 方法

使用 useVirtualSwiper 方法返回的 swiperCurrentfinalyCircularfinalyDurationonSwiperChange 都进行 swiper-view 绑定。

<template>
  <swiper
    class="swiper"
    :circular="finalyCircular"
    :current="swiperCurrent"
    :indicator-dots="false"
    :autoplay="false"
    :duration="finalyDuration"
    @change="onSwiperChange"
  >
    <swiper-item v-for="item in currentSwipers" wx:key="id" :key="item.id">
      <view
        class="swiper-item"
        :style="{ color: `rgba(${2 * item.id}, 123, ${1 * item.id})` }"
      >
        <text>{{ item.id }}</text>
        <view
          :style="{
            display: 'inline-block',
            width: '100rpx',
            height: '100rpx',
            backgroundColor: `rgba(${2 * item.id}, 123, ${1 * item.id})`,
          }"
        ></view>
      </view>
    </swiper-item>
  </swiper>
</template>

<script>
import { ref } from 'vue';
import useVirtualSwiper from './useVirtualSwiper';
export default {
  setup(props, { emits }) {
    const circular = ref(false);
    const dataSource = ref([]);

    for (let i = 0; i < 1000; i++) {
      dataSource.value.push(i);
    }

    const {
      finalyCircular,
      currentKey,
      finalyDuration,
      dataCurrent,
      swiperCurrent,
      currentSwipers,
      onSwiperChange,
    } = useVirtualSwiperCircular(
      {
        // defaultCurrent: 6,
        dataSource: dataSource.value,
        circular: circular.value,
      },
      emits
    );

    return {
      finalyDuration,
      finalyCircular,
      dataSource,
      currentKey,
      dataCurrent,
      swiperCurrent,
      currentSwipers,
      onSwiperChange,
    };
  },
};
</script>

<style lang="scss">
.swiper {
  height: 300rpx;
}
.swiper-item {
  display: block;
  height: 300rpx;
  line-height: 300rpx;
  text-align: center;
  background: #f8f8f9;
}
</style>

Component Props

Field Description Type Default
defaultCurrent 初始化默认展示 swiper 的数据索引 number 0
data swiper 数据集 Array\<string | number | object> -
circular swiper 是否可循环 boolean false
keyField 数据集主键字段名 string 'id'
duration swiper 过渡时长。过渡时长过大可能对 swiper 渲染异步数据存在影响,可根据实际场景进行调整,或者对于异步请求可以通过遮罩限制快速滑动。 number 250

还有一些 Swiper 组件支持的属性。

Field Default
indicatorColor false
indicatorActiveColor -
activeClass -
changingClass -
autoplay false
interval 5000
vertical false

Emits

EventName Description Type
current-change 数据集索引发生变化时触发(不是 swiper-view 的索引) (key: string | number, dataCurrent: number, prevCurrent: number, nextCurrent: number) => void
swiper-change swiper-view 切换时触发 (key: string | number, dataCurrent: number, swiperCurrent: number) => void

Hook Params

Field Description Type Default
defaultCurrent 初始化默认展示 swiper 的数据索引 number 0
data swiper 数据集 Array\<string | number | object> -
circular swiper 是否可循环 boolean false
keyField 数据集主键字段名 string 'id'
duration swiper 过渡时长。过渡时长过大可能对 swiper 渲染异步数据存在影响,可根据实际场景进行调整,或者对于异步请求可以通过遮罩限制快速滑动。 number 250

Hook Returns

Field Description Type
swiperCurrent swiper-view 当前展示的索引 Ref
dataCurrent 当前展示的数据索引 Ref
currentKey 当前展示的数据主键 Ref<string | number | undefined>
currentSwipers 当前展示的数据集 Ref<SwiperItem[]>
finalyKeyField 数据集的主键名 Ref
finalyDuration swiper 过渡时长 Ref
finalyCircular swiper 是否循环 Ref
onSwiperChange swiepr-view 的 change 事件处理器 (e: {current: number}) => void
scrollIntoSwiper swiper 滑动到指定的数据索引 (index: number) => void

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问