使用 vue-awesome-swiper 版本为 3.1.4 (对应的 swiper 版本为 swiper4)
// 先用原生 js + swiper4 写了一个响应式 demo.html, 每次 resize 重新 new 一个 swiper
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/css/swiper.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/js/swiper.js"></script>
<style>
.swiper-container {
position: relative;
margin: 0 auto;
}
.swiper-slide {
background-color: #eee;
text-align: center;
}
.avatar {
width: 120px;
border-radius: 50%;
/*margin: 0 auto;*/
}
p.info {
background-color: #fff;
margin-top: -60px;
margin-bottom: 0;
padding: 80px 50px 50px 50px;
color: #aaa;
font-size: 18px;
line-height: 30px;
}
.vague {
height: 100%;
position: absolute;
top: 0;
z-index: 2;
}
.vague-left {
background: linear-gradient(90deg, #f9f9fb, hsla(0, 0%, 100%, .1));
left: 0;
}
.vague-right {
background: linear-gradient(270deg, #f9f9fb, hsla(0, 0%, 100%, .1));
right: 0;
}
</style>
</head>
<body>
<div style="height: 100px"></div>
<div style="background-color: #ccc;">
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">
<img src="https://via.placeholder.com/120" alt="" class="avatar">
<p class="info">
"slider1sl ider1slid er1slider 1slider1 sli der1sli de r1sli der1slider 1slider 1slid er 1slider"
</p>
</div>
<div class="swiper-slide">
<img src="https://via.placeholder.com/120" alt="" class="avatar">
<p class="info">
"slider1sl ider1slid er1slider 1slider1 sli der1sli de r1sli der1slider 1slider 1slid er 1slide"
</p>
</div>
<div class="swiper-slide">
<img src="https://via.placeholder.com/120" alt="" class="avatar">
<p class="info">
"slider1sl ider1slid er1slider 1slider1 sli der1sli de r1sli der1slider 1slider 1slid er 1slider"
</p>
</div>
<div class="swiper-slide">
<img src="https://via.placeholder.com/120" alt="" class="avatar">
<p class="info">
"slider1sl ider1slid er1slider 1slider1 sli der1sli de "
</p>
</div>
<div class="swiper-slide">
<img src="https://via.placeholder.com/120" alt="" class="avatar">
<p class="info">
"slider1sl ider1slid er1slider 1slider1 sli der1sli de r1sli der1s"
</p>
</div>
</div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<div class="vague vague-left"></div>
<div class="vague vague-right"></div>
</div>
</div>
<script>
window.addEventListener('load', function () {
getSwipper()
window.addEventListener('resize', function () {
getSwipper()
})
})
function getSwipper() {
const client_width = document.body.clientWidth
const container = document.getElementsByClassName("swiper-container")[0]
let per_view = 2
let offset = 2
if (client_width > 992) {
container.style.width = '80%'
if (client_width > 1200) {
container.style.width = '50%'
}
const wrapper = document.getElementsByClassName("swiper-wrapper")[0]
// console.log(wrapper.clientWidth)
const item_width = (wrapper.clientWidth - 20) / 2
const vague_width = (wrapper.clientWidth - item_width - 40) / 2
offset = item_width - vague_width
const vagueObjs = document.getElementsByClassName("vague")
vagueObjs[0].style.width = vague_width + "px"
vagueObjs[1].style.width = vague_width + "px"
} else {
container.style.width = '100%'
per_view = 1
offset = 0
}
// console.log(offset)
let option = {
slidesPerView: per_view,
slidesPerGroup: 1,
spaceBetween: 20,
slidesOffsetBefore: offset,
loop: true,
// loopedSlides: 4,
prevButton: '.swiper-button-prev',
nextButton: '.swiper-button-next',
// autoplay: 1000
}
var mySwiper = new Swiper('.swiper-container', option)
}
</script>
</body>
</html>
在 vue(本次实例中使用的是 nuxt, vue 同理) 中使用则不完全一样, 因为 vue 有自己的生命周期, 在 vue 中重新生成(渲染 swiper) 可以使用 v-if = is_resizing
, 通过 resize 时 v-if = false
, resized 后 v-if = true
来实现重新渲染 dom.
// div
<div class="swiper-container">
<template v-if="swiper_visible">
<div v-swiper:mySwiper="SwiperOption">
<div class="swiper-wrapper">
<template v-for="(item,index) in list">
<div :key="index" class="swiper-slide">
<img :src="item.avatar" class="avatar">
<p class="content">{{ item.content }}</p>
</div>
</template>
</div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
</template>
</el-row>
// script
data(){
return {
mySwiperOption: {
observer: true,
observeParents: true,
slidesPerView: 2,
slidesPerGroup: 1,
spaceBetween: 20,
slidesOffsetBefore: 0,
loop: true,
// loopedSlides: 4,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
breakpoints: {
992: { //当屏幕宽度小于等于992
slidesPerView: 1,
spaceBetween: 0
},
1920: { //当屏幕宽度小于等于1920
slidesPerView: 2,
spaceBetween: 20
}
},
},
}
},
mounted() {
// 初始化 swiper
this.initSwiper()
this.swiper_visible = true
// 绑定 swiper 随 resize 变动事件
let _that = this
window.onresize = function () {
clearTimeout(this.timeout)
_that.swiper_visible = false // 注意: 这里不能写到 setTimeout 里
this.timeout = setTimeout(() => {
_that.initSwiper()
_that.swiper_visible = true
}, 500)
}
},
methods: {
// swiper 配置初始化
initSwiper() {
const client_width = document.body.clientWidth
let per_view = 2
let offset = 2
if (client_width > 992) {
const wrapper = document.getElementsByClassName("swiper-container")[0]
const item_width = (wrapper.clientWidth - 20) / 2 // 一个 slide 的宽度
const vague_width = (wrapper.clientWidth - item_width - 40) / 2 // 两侧近似半个 slide 的宽度(与 slide 间距有关)
offset = item_width - vague_width // swiper 偏移量
this.vague_width = vague_width + "px"
} else {
per_view = 1
offset = 0
this.vague_width = 0
}
this.mySwiperOption.slidesPerView = per_view
this.mySwiperOption.slidesOffsetBefore = offset
},
最重要的代码在 onresize 里, 问题如下 v-if = false 和 initSwiper() 及 v-if = true 之间要有一个时间差.
window.onresize = function () {
clearTimeout(this.timeout)
_that.swiper_visible = false // 注意: 这里不能写到 setTimeout 里
this.timeout = setTimeout(() => {
// _that.swiper_visible = false // 注意: 写在这里, 不会重新加载 swiper-dom
_that.initSwiper()
_that.swiper_visible = true
}, 500)
}
网友评论