跳转到内容

商城

刀刀
0字
0分钟
2026/8/16

视频轮播图动态轮播

思路

在商品详情页中,使用了 uView 组件库的 Awiper 轮播图组件。该组件前面介绍过,可以设置视频和图片在轮播图内。

今天测试提了一个需求:在视频播放的时候轮播图还在自动轮播,能不能视频播放时停止自动轮播,结束或暂停播放后再继续自动轮播。

查阅文档,文档上提供了 click 点击方法,可以判断用户点击的是不是视频,点击一次停止轮播,再次点击继续轮播。

但是这并不是最好的选择,他无法侦听到视频播放结束的事件。此时官方文档没有能解决我们需求的方法,官方的组件也无法满足我们的需求,我们可以复制其底层代码,自己添加事件。

本项目 uView 通过 HBuilder 导入,因此找到 uni-module 文件夹,找到 u-swiper.vue 组件,复制粘贴到自己创建的组件文件内。

源码赏析

看看别人封装的组件源码,学习学习。

他们是获取到父组件传入的数组,通过原生 swiper 轮播图组件,循环数组内容渲染到 swiper-item 上,通过 v-if 判断当前对象的类型,图片类型用 image 显示,视频类型用 video 显示。代码如下:

html
<swiper @change="change">
  <swiper-item v-for="(item, index) in list" :key="index">
    <view>
      <!-- 在nvue中,image图片的宽度默认为屏幕宽度,需要通过flex:1撑开,另外必须设置高度才能显示图片 -->
      <image
        v-if="getItemType(item) === 'image'"
        :src="getSource(item)"
        :mode="imgMode"
        @tap="clickHandler(index)"
      ></image>
      <video
        v-if="getItemType(item) === 'video'"
        :id="`video-${index}`"
        :enable-progress-gesture="false"
        :src="getSource(item)"
        @tap="clickHandler(index)"
      ></video>
    </view>
  </swiper-item>
</swiper>

<script>
  export default {
    methods: {
      getSource(item) {
        if (typeof item === 'string') return item
        if (typeof item === 'object' && this.keyName) return item[this.keyName]
        else uni.$u.error('请按格式传递列表参数')
        return ''
      },
    },
  }
</script>

这也就是为什么他要求我们在传入数组时以对象的形式,包括路径和类型的参数。

其中,视频与图片都有 @tap 点击事件,对应文档提供的 click 点击事件,其事件代码如下所示:

js
// 点击某个item
clickHandler(index) {
 this.$emit('click', index)
}

而它的轮播图组件的 change 事件则会判断当前项是否为视频,如果是视频组件,则让其暂停播放(为啥不让轮播暂停呢)。代码如下所示:

js
// 轮播切换事件
change(e) {
 // 当前的激活索引
 const {
  current
 } = e.detail
 this.pauseVideo(this.currentIndex)
 this.currentIndex = current
 this.$emit('change', e.detail)
},
// 切换轮播时,暂停视频播放
pauseVideo(index) {
 const lastItem = this.getSource(this.list[index])
 if (uni.$u.test.video(lastItem)) {
  // 当视频隐藏时,暂停播放
  const video = uni.createVideoContext(`video-${index}`, this)
  video.pause()
 }
},
// 当一个轮播item为视频时,获取它的视频海报
getPoster(item) {
 return typeof item === 'object' && item.poster ? item.poster : ''
},

修改

接下来就好办多了,为视频 video 组件添加播放 play 、暂停 pause 、停止 ended 事件,触发后分别通过 $emit() 子传父自定义事件通知父组件,如下所示:

vue
<video
  @tap="clickHandler(index)"
  @ended="noPlay()"
  @pause="noPlay()"
  @play="startPlay()"
></video>

<script>
export default {
  methods: {
    startPlay() {
      this.$emit('startPlay')
    },
    noPlay() {
      this.$emit('noPlay')
    },
  },
}
</script>

父组件通过自定义事件动态修改自动轮播的参数:

vue
<MySwiper
  keyName="url"
  :autoplay="autoplay"
  :list="bannerList"
  height="570rpx"
  indicator
  indicatorMode="dot"
  indicatorActiveColor="#f88d55"
  @noPlay="noPlay"
  @startPlay="startPlay"
></MySwiper>

<script>
export default {
  startPlay() {
    this.autoplay = false
  },
  noPlay() {
    this.autoplay = true
  },
}
</script>

现在就能够实现效果了。

微信支付

商城开通了微信支付,查阅 UniApp 支付文档 ,代码示例如下:

js
// 仅作为示例,非真实参数信息。
uni.requestPayment({
  provider: 'wxpay',
  timeStamp: String(Date.now()),
  nonceStr: 'A1B2C3D4E5',
  package: 'prepay_id=wx20180101abcdefg',
  signType: 'MD5',
  paySign: '',
  success: function (res) {
    console.log('success:' + JSON.stringify(res))
  },
  fail: function (err) {
    console.log('fail:' + JSON.stringify(err))
  },
})

可以看到,在 APP 模块中需要传到 orderInfo 对象内的参数在微信小程序中直接传递即可。其中参数如下:

参数名类型必填说明平台差异说明
timeStampString微信小程序必填时间戳从 1970 年 1 月 1 日至今的秒数,即当前的时间微信小程序
nonceStrString微信小程序必填随机字符串,长度为 32 个字符以下。微信小程序
packageString微信小程序必填统一下单接口返回的 prepay_id 参数值,提交格式如:prepay_id=xx。微信小程序
signTypeString微信小程序必填签名算法,应与后台下单时的值一致微信小程序
paySignString微信小程序必填签名,具体签名方案参见 微信小程序支付文档微信小程序

后端很贴心都把数据返回了,直接拿来使用即可。

BUG

高度 100vh 与上拉加载冲突

测试和我说某页面上拉加载更多没反应,于是开始复现。发现他没有调接口获取新数据,于是开始排查原因。

首先看看他有没有触发 onReachBottom 钩子函数,添加 connsole.log() 后查看控制台打印,发现并没有任何打印,说明没触发该钩子。

可是页面已经滚动到底部了,为什么没触发呢?百度后得知,我给外层 view 设置了高度 100vh 并 overflow: auto 的缘故,页面滚动只在该标签内滚动,而onReachBottom 监听的是页面的滚动,因此不会触发。

把外层 view 改为 min-height 和去掉 overflow 即可。代码如下:

css
<style lang="scss" scoped>
 .order {
  width: 100vw;
  min-height: 100vh;
  background-color: #f9f8fb;
  padding-bottom: 30rpx;
  box-sizing: border-box;
 }
</style>

贡献者

The avatar of contributor named as 平安喜乐 平安喜乐
The avatar of contributor named as duyidao duyidao
The avatar of contributor named as 刀刀 刀刀
The avatar of contributor named as v_duyilin v_duyilin
The avatar of contributor named as Orange Orange

页面历史

刀刀博客累计访客 人;文档累计访问量共