# swiper

组件类型:UniSwiperElement

滑块视图容器

# 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9 4.11 4.61

# 属性

名称 类型 默认值 兼容性 描述
indicator-dots boolean false
是否显示面板指示点
indicator-color string(string.ColorString) "rgba(0, 0, 0, .3)"
指示点颜色
indicator-active-color string(string.ColorString) "#000000"
当前选中的指示点颜色
disable-touch boolean false
是否禁止用户 touch 操作
easing-function string -
指定 swiper 切换缓动动画类型,有效值:default、linear、easeInCubic、easeOutCubic、easeInOutCubic
合法值 兼容性 描述
default
-
linear
-
easeInCubic
-
easeOutCubic
-
easeInOutCubic
-
autoplay boolean false
是否自动切换
current number 0
当前所在滑块的 index
current-item-id string -
当前所在滑块的 item-id ,不能与 current 被同时指定
interval number 3000
自动切换时间间隔
duration number 500
滑动动画时长(Android平台仅autoplay模式下生效)
circular boolean false
是否采用衔接滑动
vertical boolean false
滑动方向是否为纵向
rebound boolean true
控制是否回弹效果
previous-margin string -
前边距,可用于露出前一项的一小部分,接受 px 和 rpx 值
next-margin string -
后边距,可用于露出后一项的一小部分,接受 px 和 rpx 值
display-multiple-items number -
同时显示的滑块数量
@change (event: UniSwiperChangeEvent) => void -
current 改变时会触发 change 事件,event.detail = {current: current, source: source}
@transition (event: UniSwiperTransitionEvent) => void -
swiper-item 的位置发生改变时会触发 transition 事件,event.detail = {dx: dx, dy: dy}
@animationfinish (event: UniSwiperAnimationFinishEvent) => void -
动画结束时会触发 animationfinish 事件,event.detail = {current: current, source: source}

# 事件

# UniSwiperChangeEvent

# UniSwiperChangeEvent 的属性值
名称 类型 必填 默认值 兼容性 描述
detail UniSwiperChangeEventDetail - - -
名称 类型 必备 默认值 兼容性 描述
current number - - 发生change事件的滑块下标
currentItemId string -
切换结束的 swiper-item 的 item-id 属性值
source string - - autoplay 自动播放导致swiper变化;touch 用户划动引起swiper变化

# UniSwiperTransitionEvent

# UniSwiperTransitionEvent 的属性值
名称 类型 必填 默认值 兼容性 描述
detail UniSwiperTransitionEventDetail - - -
名称 类型 必备 默认值 兼容性 描述
dx number - - 横向偏移量,单位是逻辑像素px
dy number - - 纵向偏移量,单位是逻辑像素px

# UniSwiperAnimationFinishEvent

# UniSwiperAnimationFinishEvent 的属性值
名称 类型 必填 默认值 兼容性 描述
detail UniSwiperAnimationFinishEventDetail - - -
名称 类型 必备 默认值 兼容性 描述
current number - - 发生动画结束事件的滑块下标
currentItemId string -
动画结束的 swiper-item 的 item-id 属性值
source string - - autoplay 自动播放导致swiper变化;touch 用户划动引起swiper变化

# 子组件

子组件 兼容性
swiper-item

# 示例

示例为hello uni-app x alpha分支,与最新HBuilderX Alpha版同步。与最新正式版同步的master分支示例另见

扫码体验(手机浏览器跳转到App直达页)

示例

<template>
  <!-- #ifdef APP -->
  <scroll-view class="page-scroll-view">
  <!-- #endif -->
    <view class="uni-common-mb uni-common-pb">
      <page-head title="swiper,可滑动视图"></page-head>
      <view>
        <!-- 微信小程序自身Bug,autoplay为false时更新interval会导致swiper启用自动播放 -->
        <swiper id="swiper-view" class="swiper" :vertical="verticalSelect" :indicator-dots="dotsSelect"
          :autoplay="autoplaySelect" :bounces="reboundSelect" :interval="intervalSelect" :circular="circularSelect"
          :duration="durationSelect" :indicator-color="indicatorColor" :indicator-active-color="indicatorColorActive"
          :disable-touch="disableTouchSelect" :current="currentVal" :current-item-id="currentItemIdVal"
          @change="swiperChange" @transition="swiperTransition" @animationfinish="swiperAnimationfinish"
          @touchstart="swipertouchStart">
          <swiper-item item-id="A">
            <view class="swiper-item uni-bg-red"><text class="swiper-item-Text" @touchstart="viewtouchStart">A</text>
            </view>
          </swiper-item>
          <swiper-item item-id="B">
            <view class="swiper-item uni-bg-green"><text class="swiper-item-Text">B</text></view>
          </swiper-item>
          <swiper-item item-id="C">
            <view class="swiper-item uni-bg-blue"><text class="swiper-item-Text">C</text></view>
          </swiper-item>
        </swiper>
      </view>
      <view class="uni-list">
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">显示面板指示点</view>
          <switch :checked="dotsSelect" @change="dotsChange" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">定制指示器颜色</view>
          <switch :checked="indicatorColorSelect" @change="indicatorColorChange" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">禁止 touch 操作</view>
          <switch :checked="disableTouchSelect" @change="disableTouchChange" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">是否自动切换</view>
          <switch :checked="autoplaySelect" @change="autoplayChange" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">是否衔接滑动</view>
          <switch :checked="circularSelect" @change="circularChange" />
        </view>
        <view class="uni-title uni-list-cell-padding">间隔时间(毫秒)</view>
        <view class="uni-padding-wrap">
          <slider @change="sliderChange" :value="2000" :min="500" :max="5000" :show-value="true" />
        </view>
        <view class="uni-title uni-list-cell-padding">动画时长(毫秒)</view>
        <view class="uni-padding-wrap">
          <slider @change="durationSliderChange" :value="500" :min="50" :max="2000" :show-value="true" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">是否纵向滑动</view>
          <switch :checked="verticalSelect" @change="verticalChange" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">是否回弹效果</view>
          <!-- 仅 android ios harmony 支持,web 微信小程序 bounces 为 true -->
          <switch :checked="reboundSelect" @change="reboundSelectChange" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">指定current为最后一个元素</view>
          <switch :checked="currentSelect" @change="currentChange" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">指定current-item-id为最后一个元素</view>
          <switch :checked="currentItemIdSelect" @change="currentItemIdChange" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">打印 swiperChange 日志</view>
          <switch :checked="swiperChangeSelect" @change="swiperChangeChange" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">打印 swiperTransition 日志</view>
          <switch :checked="swiperTransitionSelect" @change="swiperTransitionChange" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">打印 swiperAnimationfinish 日志</view>
          <switch :checked="swiperAnimationfinishSelect" @change="swiperAnimationfinishChange" />
        </view>

        <view class="uni-list-cell-padding">测试 swiper 默认行为</view>
        <swiper class="swiper" :autoplay="autoplayForDefault" :circular="circularForDefault">
          <swiper-item item-id="A">
            <view class="swiper-item uni-bg-red"><text class="swiper-item-Text">A</text></view>
          </swiper-item>
          <swiper-item item-id="B">
            <view class="swiper-item uni-bg-green"><text class="swiper-item-Text">B</text></view>
          </swiper-item>
          <swiper-item item-id="C">
            <view class="swiper-item uni-bg-blue"><text class="swiper-item-Text">C</text></view>
          </swiper-item>
        </swiper>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">是否自动切换</view>
          <switch :checked="autoplayForDefault" @change="() => {autoplayForDefault = !autoplayForDefault}" />
        </view>
        <view class="uni-list-cell uni-list-cell-padding">
          <view class="uni-list-cell-db">是否衔接滑动</view>
          <switch :checked="circularForDefault" @change="() => {circularForDefault = !circularForDefault}" />
        </view>
        <!-- #ifndef MP -->
        <navigator url="/pages/component/swiper/swiper-list-view">
          <button type="primary">
            swiper 嵌套 list-view 测试
          </button>
        </navigator>
        <navigator url="/pages/component/swiper/swiper-anim" style="margin-top: 10px;">
        	<button type="primary">
        		swiper 动画测试
        	</button>
        </navigator>
        <!-- #endif -->

      </view>
    </view>
  <!-- #ifdef APP -->
  </scroll-view>
  <!-- #endif -->
</template>

<script>
  type SwiperEventTest = {
    type : string;
    target : UniElement | null;
    currentTarget : UniElement | null;
  }
  export default {
    data() {
      return {
        background: ['color1', 'color2', 'color3'],
        dotsSelect: false,
        reboundSelect: false,
        autoplaySelect: false,
        circularSelect: false,
        indicatorColorSelect: false,
        verticalSelect: false,
        currentSelect: false,
        currentItemIdSelect: false,
        intervalSelect: 2000,
        durationSelect: 500,
        indicatorColor: "",
        indicatorColorActive: "",
        currentVal: 0,
        currentItemIdVal: "",
        disableTouchSelect: false,
        swiperTransitionSelect: false,
        swiperAnimationfinishSelect: false,
        swiperChangeSelect: false,
        currentValChange: 0,
        autoplayForDefault: false,
        circularForDefault: false,
        // 自动化测试
        changeDetailTest: null as UniSwiperChangeEventDetail | null,
        transitionDetailTest: null as UniSwiperTransitionEventDetail | null,
        animationfinishDetailTest: null as UniSwiperAnimationFinishEventDetail | null,
        isChangeTest: '',
        isTransitionTest: '',
        isAnimationfinishTest: '',
        swipeX: 0,
        swipeY: 0
      }
    },
    onReady() {
      // #ifndef MP
      // 获取模拟滑动手势的起始点
      let ele = uni.getElementById("swiper-view")
      let eleRect = ele?.getBoundingClientRect()
      if (eleRect != null) {
        // 避开右侧边界,避免滑动行为响应为侧滑
        this.swipeX = eleRect.width - 40
        this.swipeY += eleRect.y + uni.getSystemInfoSync().safeArea.top + 44 + 35
      }
      // #endif
    },
    methods: {
      swipertouchStart(e : UniTouchEvent) {
        console.log("swiper touchstart")
      },
      viewtouchStart(e : UniTouchEvent) {
        console.log("view touchstart:")
      },
      swiperChange: function (e : UniSwiperChangeEvent) {
        this.changeDetailTest = e.detail
        this.checkEventTest({
          type: e.type,
          target: e.target,
          currentTarget: e.currentTarget
        } as SwiperEventTest, 'change')
        this.currentValChange = e.detail.current
        console.log(this.currentValChange)
        if (this.swiperChangeSelect) {
          console.log("swiperChange", e)
        }
      },
      swiperTransition: function (e : UniSwiperTransitionEvent) {
        this.transitionDetailTest = e.detail
        this.checkEventTest({
          type: e.type,
          target: e.target,
          currentTarget: e.currentTarget
        } as SwiperEventTest, 'transition')
        if (this.swiperTransitionSelect) {
          console.log("swiperTransition", e)
        }
      },
      swiperAnimationfinish: function (e : UniSwiperAnimationFinishEvent) {
        this.animationfinishDetailTest = e.detail
        this.checkEventTest({
          type: e.type,
          target: e.target,
          currentTarget: e.currentTarget
        } as SwiperEventTest, 'animationfinish')
        if (this.swiperAnimationfinishSelect) {
          console.log("swiperAnimationfinish", e)
        }
      },
      //自动化测试例专用
      jest_getSystemInfo() : GetSystemInfoResult {
        return uni.getSystemInfoSync();
      },
      // 自动化测试专用(由于事件event参数对象中存在循环引用,在ios端JSON.stringify报错,自动化测试无法page.data获取)
      checkEventTest(e : SwiperEventTest, eventName : String) {
        // #ifndef MP
        const isPass = e.type === eventName && e.target instanceof UniElement && e.currentTarget instanceof UniElement;
        // #endif
        // #ifdef MP
        const isPass = true;
        // #endif
        const result = isPass ? `${eventName}:Success` : `${eventName}:Fail`;
        switch (eventName) {
          case 'change':
            this.isChangeTest = result
            break;
          case 'transition':
            this.isTransitionTest = result
            break;
          case 'animationfinish':
            this.isAnimationfinishTest = result
            break;
          default:
            break;
        }
      },
      dotsChange: function (e : UniSwitchChangeEvent) {
        this.dotsSelect = e.detail.value
      },
      swiperTransitionChange: function (e : UniSwitchChangeEvent) {
        this.swiperTransitionSelect = e.detail.value
      },
      swiperChangeChange: function (e : UniSwitchChangeEvent) {
        this.swiperChangeSelect = e.detail.value
      },
      swiperAnimationfinishChange: function (e : UniSwitchChangeEvent) {
        this.swiperAnimationfinishSelect = e.detail.value
      },
      autoplayChange: function (e : UniSwitchChangeEvent) {
        this.autoplaySelect = e.detail.value
      },
      verticalChange: function (e : UniSwitchChangeEvent) {
        this.verticalSelect = e.detail.value
      },
      disableTouchChange: function (e : UniSwitchChangeEvent) {
        this.disableTouchSelect = e.detail.value
      },
      currentItemIdChange: function (e : UniSwitchChangeEvent) {
        this.currentItemIdSelect = e.detail.value
        if (this.currentItemIdSelect) {
          this.currentItemIdVal = 'C'
        } else {
          this.currentItemIdVal = 'A'
        }
      },
      currentChange: function (e : UniSwitchChangeEvent) {
        this.currentSelect = e.detail.value
        if (this.currentSelect) {
          this.currentVal = 2
        } else {
          this.currentVal = 0
        }

      },
      circularChange: function (e : UniSwitchChangeEvent) {
        this.circularSelect = e.detail.value
        console.log(this.circularSelect)
      },
      reboundSelectChange: function (e : UniSwitchChangeEvent) {
        this.reboundSelect = e.detail.value
        console.log(this.reboundSelect)
      },
      sliderChange(e : UniSliderChangeEvent) {
        this.intervalSelect = e.detail.value
      },
      durationSliderChange(e : UniSliderChangeEvent) {
        this.durationSelect = e.detail.value
      },
      indicatorColorChange(e : UniSwitchChangeEvent) {
        this.indicatorColorSelect = e.detail.value
        if (this.indicatorColorSelect) {
          // 选择了定制指示器颜色
          this.indicatorColor = "#ff00ff"
          this.indicatorColorActive = "#0000ff"
        } else {
          // 没有选择颜色
          this.indicatorColor = ""
          this.indicatorColorActive = ""
        }
      }
    }
  }
</script>

<style>
  .swiper {
    height: 150px;
  }

  .swiper-item {
    width: 100%;
    height: 150px;
  }

  .swiper-item-Text {
    width: 100%;
    text-align: center;
    line-height: 150px;
  }
</style>

# 参见

平台差异

  • web、小程序、App-Harmony 端swiper默认高度为150px。app端swiper默认会以内容高度作为其高度。如果要多端拉齐应自行设置swiper高度。

# swiper-item

组件类型:UniSwiperItemElement

swiper的唯一合法子组件。每个swiper-item代表一个滑块。宽高自动设置为100%

# 兼容性

Web 微信小程序 Android iOS HarmonyOS
4.0 4.41 3.9 4.11 4.61

# 属性

名称 类型 默认值 兼容性 描述
item-id string -
该 swiper-item 的标识符
skip-hidden-item-layout boolean -
(boolean)
是否跳过未显示的滑块布局,设为 true 可优化复杂情况下的滑动性能,但会丢失隐藏状态滑块的布局信息

# 参见