Vue-swiper组件封装
Vue封装swiper组件的方法
方法一:添加v-if判断是否创建DOM结构
在发送ajax请求回数据之前不创建DOM结构,等ajax请求回数据后创建DOM结构
<div id="box">
<swiper v-if="datalist.length" :loop="true">
<swiper-item v-for="data in datalist" :key="data">
<img :src="data" />
</swiper-item>
</swiper>
</div>
<script>
Vue.component("swiperItem", {
template: `
<div class="swiper-slide">
<slot></slot>
</div>
`
})
Vue.component("swiper", {
props: {
loop: {
type: Boolean,
default: true
}
},
template: `
<div class="swiper-container kerwin">
<div class="swiper-wrapper">
<slot></slot>
</div>
<div class="swiper-pagination"></div>
</div>`,
mounted() {
// console.log("mounted")
new Swiper(".kerwin", {
// direction:"vertical", //垂直
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
loop: this.loop,
autoplay: {
delay: 2500,
disableOnInteraction: false,
}
})
},
destroyed() {
// console.log("destroy")
}
})
new Vue({
el: '#box',
data: {
datalist: []
},
mounted() {
setTimeout(() => {
this.datalist = ["https://static.maizuo.com/pc/v5/usr/movie/e856bdc65507b99800f22e47801fa781.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/47aa5a3ad2ebff403d073288e4365694.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/8b0755547313706883acc771bda7709d.jpg"
]
}, 2000)
}
})
</script>
方法二:添加key值,将轮播图数组的长度作为key值
原理:数组长度一开始是0(走一次mounted钩子函数),通过ajax请求回来数据后,数据发生改变,数组长度也发生了改变;新旧虚拟DOM进过diff算法对比的时候,两个组件名都叫swiper,本应该复用的,但是因为swiper的key值不一样,所以旧的swiper会被删除(会走一次destroy钩子函数),而新的swiper即将被创建出来(再走一次mouted钩子函数),这样swiper就会重新根据数组的长度,创建出来swiper组件。
即先旧swiper执行一次mounted,然后经过数据变换进行diff算法对比,通过key的不同,旧swiper会被删除,新swiper经过diff算法对比后穿件,走一遍mounted。
<div id="box">
<swiper :key="datalist.length" :loop="true">
<swiper-item v-for="data in datalist" :key="data">
<img :src="data" />
</swiper-item>
</swiper>
</div>
<script>
Vue.component("swiperItem", {
template: `
<div class="swiper-slide">
<slot></slot>
</div>
`
})
Vue.component("swiper", {
props: {
loop: {
type: Boolean,
default: true
}
},
template: `
<div class="swiper-container kerwin">
<div class="swiper-wrapper">
<slot></slot>
</div>
<div class="swiper-pagination"></div>
</div>`,
mounted() {
// console.log("mounted")
new Swiper(".kerwin", {
// direction:"vertical", //垂直
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
loop: this.loop,
autoplay: {
delay: 2500,
disableOnInteraction: false,
}
//封装时通过属性传值来控制想要的效果,例如自动播放
})
},
destroyed() {
// console.log("destroy")
}
})
new Vue({
el: '#box',
data: {
datalist: []
},
mounted() {
setTimeout(() => {
this.datalist = ["https://static.maizuo.com/pc/v5/usr/movie/e856bdc65507b99800f22e47801fa781.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/47aa5a3ad2ebff403d073288e4365694.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/8b0755547313706883acc771bda7709d.jpg"
]
}, 2000)
}
})
</script>
方法三:通过自定义指令
原理:在Vue中通过自定义指令知道什么时候DOM创建完成,从而进行依赖DOM的库的初始化工作。在指令中传值只能传单个,若想传多个可以以数组或者对象形式传递。
自定义指令的钩子函数:
bind
:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。inserted
:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。update
:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。componentUpdated
:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind
:只调用一次,指令与元素解绑时调用。
<div id="box">
<div class="swiper-container kerwin">
<div class="swiper-wrapper">
<div
class="swiper-slide"
v-for="(data,index) in datalist"
:key="data"
v-swiper="{
index:index,
length:datalist.length
}"
>
<img :src="data" />
</div>
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
</div>
</div>
<script>
Vue.directive("swiper", {
inserted(el, binding) {
//binding.value是传来的参数,el是绑定的元素
// console.log(binding.value)
let {
index,
length
} = binding.value
if (index === length - 1) {
// new Swiper
new Swiper(".kerwin", {
// direction:"vertical", //垂直
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
loop: true,
autoplay: {
delay: 2500,
disableOnInteraction: false,
}
})
}
}
})
new Vue({
el: "#box",
data: {
datalist: [],
myname: "kerwin"
},
mounted() {
//ajax
setTimeout(() => {
this.datalist = [
"https://static.maizuo.com/pc/v5/usr/movie/e856bdc65507b99800f22e47801fa781.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/47aa5a3ad2ebff403d073288e4365694.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/8b0755547313706883acc771bda7709d.jpg"
]
}, 2000)
}
})
</script>
方法四:通过$nextTick生命周期钩子
nextTick只会执行一次,比updated执行要晚。
this.$nextTick():将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick
一样,不同的是回调的 this
自动绑定到调用它的实例上。
Vue.nextTick():在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
缺点:无复用性
<div id="box">
<div class="swiper-container kerwin">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="data in datalist" :key="data">
<img :src="data" />
</div>
</div>
<!-- 如果需要分页器 -->
<div class="swiper-pagination"></div>
</div>
</div>
<script>
var vm = new Vue({
el: "#box",
data: {
datalist: [],
myname: "kerwin"
},
mounted() {
//ajax
setTimeout(() => {
this.datalist = [
"https://static.maizuo.com/pc/v5/usr/movie/e856bdc65507b99800f22e47801fa781.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/47aa5a3ad2ebff403d073288e4365694.jpg",
"https://static.maizuo.com/pc/v5/usr/movie/8b0755547313706883acc771bda7709d.jpg"
]
this.$nextTick(() => {
//console.log("我比updated执行的都晚,而且只执行一次")
new Swiper(".kerwin", {
// direction:"vertical", //垂直
// 如果需要分页器
pagination: {
el: '.swiper-pagination',
},
loop: true,
autoplay: {
delay: 2500,
disableOnInteraction: false,
}
})
})
}, 2000)
},
updated() {
//console.log("updated")
}
})
</script>