| New file | 
 |  |  | 
 |  |  | <template> | 
 |  |  |    <view | 
 |  |  |       class="u-swiper" | 
 |  |  |       :style="{ | 
 |  |  |          backgroundColor: bgColor, | 
 |  |  |          height: $u.addUnit(height), | 
 |  |  |          borderRadius: $u.addUnit(radius) | 
 |  |  |       }" | 
 |  |  |    > | 
 |  |  |       <view | 
 |  |  |          class="u-swiper__loading" | 
 |  |  |          v-if="loading" | 
 |  |  |       > | 
 |  |  |          <u-loading-icon mode="circle"></u-loading-icon> | 
 |  |  |       </view> | 
 |  |  |       <swiper | 
 |  |  |          v-else | 
 |  |  |          class="u-swiper__wrapper" | 
 |  |  |          :style="{ | 
 |  |  |             height: $u.addUnit(height), | 
 |  |  |          }" | 
 |  |  |          @change="change" | 
 |  |  |          :circular="circular" | 
 |  |  |          :interval="interval" | 
 |  |  |          :duration="duration" | 
 |  |  |          :autoplay="autoplay" | 
 |  |  |          :current="current" | 
 |  |  |          :currentItemId="currentItemId" | 
 |  |  |          :previousMargin="$u.addUnit(previousMargin)" | 
 |  |  |          :nextMargin="$u.addUnit(nextMargin)" | 
 |  |  |          :acceleration="acceleration" | 
 |  |  |          :displayMultipleItems="displayMultipleItems" | 
 |  |  |          :easingFunction="easingFunction" | 
 |  |  |       > | 
 |  |  |          <swiper-item | 
 |  |  |             class="u-swiper__wrapper__item" | 
 |  |  |             v-for="(item, index) in list" | 
 |  |  |             :key="index" | 
 |  |  |          > | 
 |  |  |             <view | 
 |  |  |                class="u-swiper__wrapper__item__wrapper" | 
 |  |  |                :style="[itemStyle(index)]" | 
 |  |  |             > | 
 |  |  |                <!-- 在nvue中,image图片的宽度默认为屏幕宽度,需要通过flex:1撑开,另外必须设置高度才能显示图片 --> | 
 |  |  |                <image | 
 |  |  |                   class="u-swiper__wrapper__item__wrapper__image" | 
 |  |  |                   v-if="getItemType(item) === 'image'" | 
 |  |  |                   :src="getSource(item)" | 
 |  |  |                   :mode="imgMode" | 
 |  |  |                   @tap="clickHandler(index)" | 
 |  |  |                   :style="{ | 
 |  |  |                      height: $u.addUnit(height), | 
 |  |  |                      borderRadius: $u.addUnit(radius) | 
 |  |  |                   }" | 
 |  |  |                ></image> | 
 |  |  |                <video | 
 |  |  |                   class="u-swiper__wrapper__item__wrapper__video" | 
 |  |  |                   v-if="getItemType(item) === 'video'" | 
 |  |  |                   :id="`video-${index}`" | 
 |  |  |                   :enable-progress-gesture="false" | 
 |  |  |                   :src="getSource(item)" | 
 |  |  |                   :poster="getPoster(item)" | 
 |  |  |                   :title="showTitle && $u.test.object(item) && item.title ? item.title : ''" | 
 |  |  |                   :style="{ | 
 |  |  |                      height: $u.addUnit(height) | 
 |  |  |                   }" | 
 |  |  |                   controls | 
 |  |  |                   @tap="clickHandler(index)" | 
 |  |  |                ></video> | 
 |  |  |                <text | 
 |  |  |                   v-if="showTitle && $u.test.object(item) && item.title && $u.test.image(getSource(item))" | 
 |  |  |                   class="u-swiper__wrapper__item__wrapper__title u-line-1" | 
 |  |  |                >{{ item.title }}</text> | 
 |  |  |             </view> | 
 |  |  |          </swiper-item> | 
 |  |  |       </swiper> | 
 |  |  |       <view class="u-swiper__indicator" :style="[$u.addStyle(indicatorStyle)]"> | 
 |  |  |          <slot name="indicator"> | 
 |  |  |             <u-swiper-indicator | 
 |  |  |                v-if="!loading && indicator && !showTitle" | 
 |  |  |                :indicatorActiveColor="indicatorActiveColor" | 
 |  |  |                :indicatorInactiveColor="indicatorInactiveColor" | 
 |  |  |                :length="list.length" | 
 |  |  |                :current="currentIndex" | 
 |  |  |                :indicatorMode="indicatorMode" | 
 |  |  |             ></u-swiper-indicator> | 
 |  |  |          </slot> | 
 |  |  |       </view> | 
 |  |  |    </view> | 
 |  |  | </template> | 
 |  |  |  | 
 |  |  | <script> | 
 |  |  |    import props from './props.js'; | 
 |  |  |    /** | 
 |  |  |     * Swiper 轮播图 | 
 |  |  |     * @description 该组件一般用于导航轮播,广告展示等场景,可开箱即用, | 
 |  |  |     * @tutorial https://www.uviewui.com/components/swiper.html | 
 |  |  |     * @property {Array}         list               轮播图数据 | 
 |  |  |     * @property {Boolean}         indicator            是否显示面板指示器(默认 false ) | 
 |  |  |     * @property {String}         indicatorActiveColor   指示器非激活颜色(默认 '#FFFFFF' ) | 
 |  |  |     * @property {String}         indicatorInactiveColor   指示器的激活颜色(默认 'rgba(255, 255, 255, 0.35)' ) | 
 |  |  |     * @property {String | Object}   indicatorStyle         指示器样式,可通过bottom,left,right进行定位 | 
 |  |  |     * @property {String}         indicatorMode         指示器模式(默认 'line' ) | 
 |  |  |     * @property {Boolean}         autoplay            是否自动切换(默认 true ) | 
 |  |  |     * @property {String | Number}   current               当前所在滑块的 index(默认 0 ) | 
 |  |  |     * @property {String}         currentItemId         当前所在滑块的 item-id ,不能与 current 被同时指定 | 
 |  |  |     * @property {String | Number}   interval            滑块自动切换时间间隔(ms)(默认 3000 ) | 
 |  |  |     * @property {String | Number}   duration            滑块切换过程所需时间(ms)(默认 300 ) | 
 |  |  |     * @property {Boolean}         circular            播放到末尾后是否重新回到开头(默认 false ) | 
 |  |  |     * @property {String | Number}   previousMargin         前边距,可用于露出前一项的一小部分,nvue和支付宝不支持(默认 0 ) | 
 |  |  |     * @property {String | Number}   nextMargin            后边距,可用于露出后一项的一小部分,nvue和支付宝不支持(默认 0 ) | 
 |  |  |     * @property {Boolean}         acceleration         当开启时,会根据滑动速度,连续滑动多屏,支付宝不支持(默认 false ) | 
 |  |  |     * @property {Number}         displayMultipleItems   同时显示的滑块数量,nvue、支付宝小程序不支持(默认 1 ) | 
 |  |  |     * @property {String}         easingFunction         指定swiper切换缓动动画类型, 只对微信小程序有效(默认 'default' ) | 
 |  |  |     * @property {String}         keyName               list数组中指定对象的目标属性名(默认 'url' ) | 
 |  |  |     * @property {String}         imgMode               图片的裁剪模式(默认 'aspectFill' ) | 
 |  |  |     * @property {String | Number}   height               组件高度(默认 130 ) | 
 |  |  |     * @property {String}         bgColor               背景颜色(默认    '#f3f4f6' ) | 
 |  |  |     * @property {String | Number}   radius               组件圆角,数值或带单位的字符串(默认 4 ) | 
 |  |  |     * @property {Boolean}         loading               是否加载中(默认 false ) | 
 |  |  |     * @property {Boolean}         showTitle            是否显示标题,要求数组对象中有title属性(默认 false ) | 
 |  |  |     * @event {Function(index)}   click   点击轮播图时触发   index:点击了第几张图片,从0开始 | 
 |  |  |     * @event {Function(index)}   change   轮播图切换时触发(自动或者手动切换)   index:切换到了第几张图片,从0开始 | 
 |  |  |     * @example   <u-swiper :list="list4" keyName="url" :autoplay="false"></u-swiper> | 
 |  |  |     */ | 
 |  |  |    export default { | 
 |  |  |       name: 'u-swiper', | 
 |  |  |       mixins: [uni.$u.mpMixin, uni.$u.mixin, props], | 
 |  |  |       data() { | 
 |  |  |          return { | 
 |  |  |             currentIndex: 0 | 
 |  |  |          } | 
 |  |  |       }, | 
 |  |  |       watch: { | 
 |  |  |          current(val, preVal) { | 
 |  |  |             if(val === preVal) return; | 
 |  |  |             this.currentIndex = val; // 和上游数据关联上 | 
 |  |  |          } | 
 |  |  |       }, | 
 |  |  |       computed: { | 
 |  |  |          itemStyle() { | 
 |  |  |             return index => { | 
 |  |  |                const style = {} | 
 |  |  |                // #ifndef APP-NVUE || MP-TOUTIAO | 
 |  |  |                // 左右流出空间的写法不支持nvue和头条 | 
 |  |  |                // 只有配置了此二值,才加上对应的圆角,以及缩放 | 
 |  |  |                if (this.nextMargin && this.previousMargin) { | 
 |  |  |                   style.borderRadius = uni.$u.addUnit(this.radius) | 
 |  |  |                   if (index !== this.currentIndex) style.transform = 'scale(0.92)' | 
 |  |  |                } | 
 |  |  |                // #endif | 
 |  |  |                return style | 
 |  |  |             } | 
 |  |  |          } | 
 |  |  |       }, | 
 |  |  |       methods: { | 
 |  |  |       getItemType(item) { | 
 |  |  |         if (typeof item === 'string') return uni.$u.test.video(this.getSource(item)) ? 'video' : 'image' | 
 |  |  |         if (typeof item === 'object' && this.keyName) { | 
 |  |  |           if (!item.type) return uni.$u.test.video(this.getSource(item)) ? 'video' : 'image' | 
 |  |  |           if (item.type === 'image') return 'image' | 
 |  |  |           if (item.type === 'video') return 'video' | 
 |  |  |           return 'image' | 
 |  |  |         } | 
 |  |  |       }, | 
 |  |  |          // 获取目标路径,可能数组中为字符串,对象的形式,额外可指定对象的目标属性名keyName | 
 |  |  |          getSource(item) { | 
 |  |  |             if (typeof item === 'string') return item | 
 |  |  |             if (typeof item === 'object' && this.keyName) return item[this.keyName] | 
 |  |  |             else uni.$u.error('请按格式传递列表参数') | 
 |  |  |             return '' | 
 |  |  |          }, | 
 |  |  |          // 轮播切换事件 | 
 |  |  |          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 : '' | 
 |  |  |          }, | 
 |  |  |          // 点击某个item | 
 |  |  |          clickHandler(index) { | 
 |  |  |             this.$emit('click', index) | 
 |  |  |          } | 
 |  |  |       }, | 
 |  |  |    } | 
 |  |  | </script> | 
 |  |  |  | 
 |  |  | <style lang="scss" scoped> | 
 |  |  |    @import "../../libs/css/components.scss"; | 
 |  |  |  | 
 |  |  |    .u-swiper { | 
 |  |  |       @include flex; | 
 |  |  |       justify-content: center; | 
 |  |  |       align-items: center; | 
 |  |  |       position: relative; | 
 |  |  |       overflow: hidden; | 
 |  |  |  | 
 |  |  |       &__wrapper { | 
 |  |  |          flex: 1; | 
 |  |  |  | 
 |  |  |          &__item { | 
 |  |  |             flex: 1; | 
 |  |  |  | 
 |  |  |             &__wrapper { | 
 |  |  |                @include flex; | 
 |  |  |                position: relative; | 
 |  |  |                overflow: hidden; | 
 |  |  |                transition: transform 0.3s; | 
 |  |  |                flex: 1; | 
 |  |  |  | 
 |  |  |                &__image { | 
 |  |  |                   flex: 1; | 
 |  |  |                } | 
 |  |  |  | 
 |  |  |                &__video { | 
 |  |  |                   flex: 1; | 
 |  |  |                } | 
 |  |  |  | 
 |  |  |                &__title { | 
 |  |  |                   position: absolute; | 
 |  |  |                   background-color: rgba(0, 0, 0, 0.3); | 
 |  |  |                   bottom: 0; | 
 |  |  |                   left: 0; | 
 |  |  |                   right: 0; | 
 |  |  |                   font-size: 28rpx; | 
 |  |  |                   padding: 12rpx 24rpx; | 
 |  |  |                   color: #FFFFFF; | 
 |  |  |                   flex: 1; | 
 |  |  |                } | 
 |  |  |             } | 
 |  |  |          } | 
 |  |  |       } | 
 |  |  |  | 
 |  |  |       &__indicator { | 
 |  |  |          position: absolute; | 
 |  |  |          bottom: 10px; | 
 |  |  |       } | 
 |  |  |    } | 
 |  |  | </style> |