效果如图:
2.本例中使用 setTimeout 模拟异步获取数据,使用了 swiper组件
1.轮播初始化放在 updated 中,(弊端 :如果当前页面的状态不止 datalist 一个,其他状态更新时也会触发 new swiper,这个时候 new swiper 执行多次,就会出 bug)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./swiper-7.4.1/swiper/swiper-bundle.min.css">
<script src="./vue.js"></script>
<script src="./swiper-7.4.1/swiper/swiper-bundle.min.js"></script>
<style>
.swiper {
width: 600px;
height: 300px;
}
</style>
</head>
<body>
<div id="box">
<div class="swiper">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for = "items in datalist" :key="items">
<img :src="items">
</div>
</div>
</div>
<!-- 如果需要导航按钮 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
<script>
var vm = new Vue({
el:'#box',
data:{
datalist:[]
},
mounted(){
setTimeout(()=>{
this.datalist = [
'https://mall.s.maizuo.com/bb4e79ef1de07aab2f8ed91b7fd7e731.jpg',
'https://mall.s.maizuo.com/90b7581c565efdf1b3ed8127172d9c87.jpg',
'https://mall.s.maizuo.com/e753ab0a0709ff8a7048da1c714c5e06.jpg'
]
},2000)
},
updated(){
new Swiper ('.swiper', {
loop: true, // 循环模式选项
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
})
}
})
/*
这个方法的缺点:1 无法复用;2.如果当前页面的状态不止 datalist 一个,其他状态更新时也会触发 new swiper,这个时候
new swiper 执行多次,就会出 bug
*/
</script>
</body>
</html>
2.轮播初始化放在 mounted 中,用组件方式。提高 复用性。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./swiper-7.4.1/swiper/swiper-bundle.min.css">
<script src="./vue.js"></script>
<script src="./swiper-7.4.1/swiper/swiper-bundle.min.js"></script>
<style>
.swiper {
width: 600px;
height: 300px;
}
</style>
</head>
<body>
<div id="box">
<!-- 一开始的 key = 0, 当 2s 后取到后端数据时, key 为数组长度, 进行 diff 算法
对比发现前后两个 swiper 不一样(因为 diff 算法中 key 值对比),于是删除老的,重新创建新的 dom 结构。
于是 mounted 触发两次,即第一次创建的 没有轮播内容 dom 和第二次取得数据后,两下对比发现
第一次创建的 dom 不能复用,删除后重新创建新的 dom -->
<swiper :key= "datalist.length"> <!-- 这个方法是一样的 。<swiper v-if = "datalist.length"></swiper> -->
<swiper-item v-for="items in datalist" :key="items">
<img :src="items">
</swiper-item>
</swiper>
</div>
<script>
Vue.component("swiperItem",{
template:`
<div class="swiper-slide">
<slot></slot>
</div>
`
}),
Vue.component("swiper",{
template:`
<div class="swiper">
<div class="swiper-wrapper">
<slot></slot>
</div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
`,
mounted(){
console.log("mounted")
new Swiper ('.swiper', {
loop: true,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
})
},
destroyed(){
console.log("destroy","第一次创建的 dom 结束了!")
}
})
new Vue({
el:'#box',
data:{
datalist:[]
},
mounted(){
setTimeout(()=>{
this.datalist = [
'https://mall.s.maizuo.com/bb4e79ef1de07aab2f8ed91b7fd7e731.jpg',
'https://mall.s.maizuo.com/90b7581c565efdf1b3ed8127172d9c87.jpg',
'https://mall.s.maizuo.com/e753ab0a0709ff8a7048da1c714c5e06.jpg'
]
},2000)
},
})
</script>
</body>
</html>
3.用指令的方式实现轮播,因为指令可以知道 dom 节点什么时候创建完成。(vue2)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./swiper-7.4.1/swiper/swiper-bundle.min.css">
<script src="./vue.js"></script>
<script src="./swiper-7.4.1/swiper/swiper-bundle.min.js"></script>
<style>
.swiper {
width: 300px;
height: 150px;
}
</style>
</head>
<body>
<div id="box">
<div class="swiper">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for = "(items,index) in datalist" :key="items"
v-swiper="{
index:index,
length:datalist.length
}">
<img :src="items">
</div>
</div>
<!-- 导航按钮 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
</div>
<script>
Vue.directive("swiper",{
inserted(el,binding){
console.log(this)
console.log(el,binding)
let {
index,length
} = binding.value
if(index === length-1){
new Swiper ('.swiper', {
loop: true, // 循环模式选项
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
})
}
}
})
var vm = new Vue({
el:'#box',
data:{
datalist:[]
},
mounted(){
setTimeout(()=>{
this.datalist = [
'https://mall.s.maizuo.com/bb4e79ef1de07aab2f8ed91b7fd7e731.jpg',
'https://mall.s.maizuo.com/90b7581c565efdf1b3ed8127172d9c87.jpg',
'https://mall.s.maizuo.com/e753ab0a0709ff8a7048da1c714c5e06.jpg'
]
},2000)
}
})
</script>
</body>
</html>
4.用指令的方式轮播(vue3)指令的生命周期 2中的 inserted 换成了 mounted。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./swiper-7.4.1/swiper/swiper-bundle.min.css">
<script src="https://cdn.staticfile.org/vue/3.0.5/vue.global.js"></script>
<script src="./swiper-7.4.1/swiper/swiper-bundle.min.js"></script>
<style>
.swiper {
width: 300px;
height: 150px;
}
</style>
</head>
<body>
<div id="box">
<div class="swiper">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for = "(items,index) in datalist" :key="items"
v-swiper="{
index:index,
length:datalist.length
}">
<img :src="items">
</div>
</div>
<!-- 导航按钮 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
</div>
<script>
var obj = {
data(){
return {
datalist:[]
}
},
mounted(){
setTimeout(()=>{
this.datalist = [
'https://mall.s.maizuo.com/bb4e79ef1de07aab2f8ed91b7fd7e731.jpg',
'https://mall.s.maizuo.com/90b7581c565efdf1b3ed8127172d9c87.jpg',
'https://mall.s.maizuo.com/e753ab0a0709ff8a7048da1c714c5e06.jpg'
]
},2000)
}
}
var app = Vue.createApp(obj)
app.directive("swiper",{
mounted(el,binding){
console.log(this)
console.log(el,binding)
let {
index,length
} = binding.value
if(index === length-1){
new Swiper ('.swiper', {
loop: true, // 循环模式选项
// 如果需要前进后退按钮
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
autoplay: {
delay: 1000,
disableOnInteraction: false,
},
})
}
}
})
app.mount('#box')
</script>
</body>
</html>
5.用 nextTick,没有复用性。当前节点状态什么时候更新到dom 就会触发一次。