问题:
在vue中使用swiper 就是不知道什么时候dom元素创建完成,我们把swiper的初始化(new swiper)最后放在了updated生命周期中,可以正常使用;但是复用性能不好,且updated时会频繁更新,会造成多次swiper初始化实例。
解决方法(以下三种):
1.封装组件,可以提高复用性,且new swiper 放在组件中的mounted 生命周期中不会影响性能;
head中引入一下文件:
// 需要引入swiper-bundle.min.css
<link rel="stylesheet" href="../swiper/swiper-bundle.min.css">
// 引入swiper-bundle.min.js
<script src="../swiper/swiper-bundle.min.js"></script>
<script src="../vue.js"></script>
<div id="box">
<swiper v-if="datalist.length">
<swiper-item v-for="data in datalist" :key="data">
<img :src="data">
</swiper-item>
</swiper>
</div>
*{
margin:0;
padding:0;
}
.swiper {
width: 100%;
height: 600px;
}
.swiper img{
width: 100%;
}
//vue 2.0写法
// 轮播的每一个小box 组件
Vue.component('swiperItem',{
template:`
<div class="swiper-slide">
<slot></slot>
</div>
`
})
//控制显示区域的大盒子 组件
Vue.component('swiper',{
template:` <div class="swiper new_swiper">
<div class="swiper-wrapper">
<slot></slot>
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
</div>`,
mounted(){
// 现在在组件中,执行new swiper 初始化,提高复用性
new Swiper ('.new_swiper', {
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
autoplay: {
delay: 2000,
stopOnLastSlide: false,
disableOnInteraction: true,
}
})
}
})
// vue实例初始化
var vm = new Vue({
el:"#box",
data:{
datalist:[]
},
mounted(){
// 模拟ajax请求数据
// 照片我用的本地,可以随便给一组可以访问到的照片地址数据
setTimeout(()=>{
this.datalist = [
"../images/1.jpeg",
"../images/2.jpeg",
"../images/3.jpeg"
]
},2000);
},
updated(){
// 以前new swiper 写在这里;复用性不好
}
})
2.使用vue 中的自定义指令写法;
自定义指令的作用:通过绑定自定义指令,可以知道dom元素什么时候可以创建完成;
//头部同样需要引入相关文件
<div id="box">
<div class="swiper new_swiper">
<div class="swiper-wrapper">
// vue自定义指令v-swiper 可以获取到什么时候dom 元素创建完成;
<div class="swiper-slide" v-for="item,index in datalist" :key="item" v-swiper="{
index:index,
length:datalist.length
}">
<img :src="item">
</div>
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
</div>
</div>
// vue 2.0 写法
Vue.directive('swiper',{
// 创建一个绑定指令的dom元素,就会执行一次inserted;
//不能直接初始化swiper,应该是创建完最后一个slide再初始化
inserted(el,binding){
// 我们让 index 等于 数据长度-1 就是就说明是最后一个dom元素了
// 指令只能传一个值,我们想要传多个值,通过封装到对象中,然后再获取
// es6 解构赋值
let {index,length} = binding.value;
//判断 是最后一个dom元素创建完成再初始化
if(index === length-1){
// 执行初始化
init();
}
}
})
// vue 实例化
var vm = new Vue({
el:"#box",
data:{
datalist:[]
},
mounted(){
setTimeout(()=>{
this.datalist = [
"../images/1.jpeg",
"../images/2.jpeg",
"../images/3.jpeg"
]
},2000);
}
})
// swiper初始化
function init(){
var mySwiper = new Swiper ('.new_swiper', {
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
autoplay: {
delay: 2000,
stopOnLastSlide: false,
disableOnInteraction: true,
}
})
}
3.使用nextTick方法;
//html 代码如上
<div id="box">
<div class="swiper new_swiper">
<div class="swiper-wrapper">
// vue自定义指令v-swiper 可以获取到什么时候dom 元素创建完成;
<div class="swiper-slide" v-for="item,index in datalist" :key="item" v-swiper="{
index:index,
length:datalist.length
}">
<img :src="item">
</div>
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
</div>
</div>
// 注意:这个使用了vue 3.0 写法,可以自己改
var obj = {
data(){
return {
datalist:[]
}
},
mounted(){
setTimeout(()=>{
this.datalist = [
"../images/1.jpeg",
"../images/2.jpeg",
"../images/3.jpeg"
]
// nextTick 用法 比updated 执行的还晚,并且只执行一次
this.$nextTick(()=>
//在这里执行swiper 初始化
init();
});
},2000);
}
}
// vue3.0写法
var app = Vue.createApp(obj);
app.mount("#box");
// swiper初始化
function init(){
var mySwiper = new Swiper ('.new_swiper', {
loop: true, // 循环模式选项
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
autoplay: {
delay: 2000,
stopOnLastSlide: false,
disableOnInteraction: true,
}
})
}