父组件
<template>
<div class="swipe-demo">
<ui-swipe :imgList="imgList">
<div
v-for="(item, ind) in imgList"
:key="ind"
@click="handleClick(item)"
class="swiper-img"
>
<img :src="item.picUrl" />
</div>
</ui-swipe>
</div>
</template>
<script>
export default {
name: "swipe-demo",
data() {
return {
imgList: [
{
picUrl: require("../../../assets/components/list-3.png"),
picLink: "https://baidu1.com",
},
{
picUrl: require("../../../assets/components/list-3.png"),
picLink: "https://baidu2.com",
},
{
picUrl: require("../../../assets/components/list-3.png"),
picLink: "https://baidu3.com",
},
{
picUrl: require("../../../assets/components/list-3.png"),
picLink: "https://baidu1.com",
},
{
picUrl: require("../../../assets/components/list-3.png"),
picLink: "https://baidu2.com",
},
{
picUrl: require("../../../assets/components/list-3.png"),
picLink: "https://baidu3.com",
},
],
};
},
mounted() {},
methods: {
handleClick(val) {
console.log(val);
},
},
};
</script>
<style lang="scss">
.swipe-demo {
font-size: 24px;
}
</style>
子组件
<template>
<div
class="ui-swiper"
@touchstart="onTouchStart"
@touchend="onTouchEnd"
:style="{ height: height }"
>
<div :style="[ulStyle, swiperStyle]" class="swiper-box">
<slot></slot>
</div>
<div
v-if="options.swiperNumShow"
:class="[options.swiperNum == '' ? 'swiper-num' : 'swiper-num-size']"
>
<span class="swiper-num-style">{{ index + 1 }}</span
><span class="swiper-num-style2">/{{ imgList.length }}</span>
</div>
<div v-if="options.arrowShow">
<img
class="ui-swiper-right"
src="../../assets/components/arrow_right.png"
alt=""
@click="$_onRight"
/>
<img
class="ui-swiper-left"
src="../../assets/components/arrow_left.png"
alt=""
@click="$_onLeft"
/>
</div>
<div v-show="options.showDots" class="swiper-dots">
<div
v-for="(item, ind) in imgList"
:key="ind"
:class="[
options.dotsType == 'rect' ? 'dots-item-box' : 'dots-item',
index === ind ? 'active' : '',
]"
></div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
ulStyle: { width: screen.width },
itemWidth: screen.width,
swiperStyle: {},
index: 0,
touchStart: {},
touchEnd: {},
intervalTime: "",
};
},
props: {
height: {
type: String,
default: "200px",
},
options: {
type: Object,
default() {
return {
showDots: true,
interval: 5000,
autoplay: true,
swiperNumShow: false,
dotsType: "dot",
swiperNum: "",
arrowShow:false,
};
},
},
imgList: {
type: Array,
},
},
mounted() {
this.calcWidth();
this.handleLoopMove();
},
methods: {
calcWidth() {
this.$nextTick(function () {
let length = this.imgList.length;
this.ulStyle.width = parseInt(this.itemWidth * length) + "px";
});
},
handleMove() {
let moveX = this.itemWidth * this.index;
if (this.index === 0) {
moveX = 0;
}
this.swiperStyle = {
transform: "translateX(-" + moveX + "px)",
};
},
handleLoopMove() {
if (this.options.autoplay) {
let interval = this.options.interval ? this.options.interval : 5000;
let len = this.imgList.length;
this.intervalTime = setInterval(() => {
if (
this.index == this.imgList.length - 1 ||
len != this.imgList.length
) {
this.index--;
if (this.index == 0) {
len = this.imgList.length;
} else {
len--;
}
} else if (len == this.imgList.length) {
this.index++;
}
this.handleMove();
}, interval);
}
},
onTouchStart(e) {
this.touchStart = e.changedTouches[0];
clearInterval(this.intervalTime);
},
onTouchEnd(e) {
this.touchEnd = e.changedTouches[0];
if (this.touchEnd.clientX - this.touchStart.clientX > 60) {
this.index--;
if (this.index <= 0) {
this.index = 0;
}
} else if (this.touchEnd.clientX - this.touchStart.clientX < -60) {
this.index++;
if (this.index >= this.imgList.length - 1) {
this.index = this.imgList.length - 1;
}
}
this.handleMove();
this.handleLoopMove();
},
$_onLeft(){
if(this.index >0 && this.index<this.imgList.length){
this.index--;
this.handleMove();
}
},
$_onRight(){
if(this.index >=0 && this.index<this.imgList.length-1){
this.index++;
this.handleMove();
}
}
},
watch: {
imgList: function (e) {
this.calcWidth();
},
},
destroyed() {
if (this.autoplay) {
clearInterval(this.intervalTime);
}
},
};
</script>
<style lang="scss">
.ui-swiper {
overflow: hidden;
position: relative;
.swiper-box {
white-space: nowrap;
height: 100%;
transition: 0.5s ease;
display: flex;
.swiper-img {
list-style: none;
height: 100%;
width: 100%;
overflow: hidden;
img {
width: 100%;
height: 100%;
}
&.zoom {
transition: 0.5s ease;
}
}
}
.swiper-num {
position: absolute;
bottom: 20px;
right: 20px;
background: rgba(0, 0, 0, 0.5);
color: #fff;
padding: 5px 15px;
border-radius: 25px;
font-size: 24px;
}
.swiper-num-size {
position: absolute;
top: 20px;
right: 20px;
.swiper-num-style {
font-size: 36px;
}
.swiper-num-style2 {
font-size: 28px;
color: #9ba0aa;
}
}
.swiper-dots {
position: absolute;
bottom: 16px;
left: 50%;
transform: translateX(-50%);
display: flex;
.dots-item {
width: 15px;
height: 15px;
border-radius: 50%;
background: rgba(0, 0, 0, 0.3);
margin: 0 4px;
&.active {
background: #409eff;
}
}
.dots-item-box {
width: 20px;
height: 5px;
background: rgba(0, 0, 0, 0.3);
margin: 0 4px;
&.active {
background: #409eff;
}
}
}
.ui-swiper-right {
position: absolute;
top: 40%;
right: 3%;
}
.ui-swiper-left {
position: absolute;
top: 40%;
left: 3%;
}
}
</style>