在前面讲到 Vue组件的封装不知道还记不记得,这里就不在过多的赘述,这里附上链接跳转可以进行回顾翻阅,上一篇内容讲到这个自定义的指令,也就是为这篇封装swiper组件使用指令做铺垫的,那么也一同附在这里:
第三十七篇 Vue中封装Swiper组件
第三十八篇 Vue中封装Swiper组件 2.0
第三十九篇 自定义指令 - directive
自定义指令 - v-swiper
在这之前封装swiper组件所遇到的问题就是swiper什么时候开始进行初始化的问题,不是初始化过早,就是会被重复执行,所以需要知道到底在什么时机来对swiper进行初始化?上一篇内容讲到自定义指令当中我们知道自定义指令其实就是操作底层DOM,但目的并不一定是非要去操作DOM,虽然大多时候需要去操作DOM需求其实并不多,但是有时候需要知道的是DOM在什么时候会被刚刚创建完;封装swiper组件时我们就是在寻找DOM在什么时候会被创建出来,swiper好进行初始化内容,这样一来就不会造成具有初始化过早之类的问题,那么指令当中有一个指令生命周期inserted,当绑定该指令的标签插入父节点的时候就会触发;下面先来一段代码:
<div id="app">
<div class="swiper-container mySwiper">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="item in swiperList" :key="index">
<img :src="item" alt="">
</div>
<div class="swiper-pagination"></div>
</div>
</div>
</div>
<script>
new Vue({
el:'#app',
data:{
swiperList:[]
},
mounted(){
// 假设请求回来的数据赋值给swiperList
this.swiperList = [
'ImageOne' ,
'ImageTwo' ,
'ImageThree' ];
// new Swiper(".author")
},2000)
}
})
</script>
通过之前内容的学习能够知道Swiper在请求数据完成做初始化并不能够让swiper轮播起来,即初始化过早,需要知道DOM什么时候创建,这段数据会在DOM创建完插入父节点当中再进行初始化才能轮播;
下面来编写v-swiper自定义指令,在控制台上了解指令绑定的标签插入父节点的过程:
<div id="app">
...
<div class="swiper-slide" v-for="item in swiperList" :key="item" v-swiper>
<img :src="item" alt="">
</div>
...
</div>
<script>
Vue.directive("swiper",{
inserted(el){
console.log(el);
}
})
当绑有 v-swiper 指令的标签插入父节点当中,会打印原生DOM节点;
那么知道这个时机不就可以做swiper初始化的内容,那么能直接讲new Swiper的内容移到inserted当中吗?测试一下:
1. 编写代码:
<script>
Vue.directive("swiper",{
inserted(el){
console.log(el);
new Swiper(".mySwiper",{
loop:true,
pagination:{
el:'.swiper-pagination'
}
})
}
})
2. 测试效果:
这又是为什么?每插入一条数据都会触发inserted走一遍,这里其实仅仅只需要知道是否全部已经插入到父节点当中,不需要每一条都触发一次,只需判断最后一条数据是否插入完成,这就意味着整个内容已经插入到父节点的内容了,也就是 if (最后一个节点插入){ 进行swiper初始化 },怎么去判断是否是最后一个节点呢?通过当前的索引值和swiperList的长度进行判断,当索引index等于swiperList.length - 1时再触发swiper的初始化,索引值index可以通过v-swiper指令进行传值,swiperList.length怎么获取得到呢?this.swiperList.length? 看一下this指向
console.log(el,this);
this是指向window,这样一来拿不到,这里可以更组件进行类比,组件也不能轻易拿到父组件的状态,组件要通过通信才拿到,指令可以传过来index一个变量,那么通过指令其实也可以传递一个对象,以对象的方式传过来不久可以了。
<div class="swiper-slide" v-for="(item,index) in swiperList" :key="item"
v-swiper="{ current:index , length : swiperList.length }">
<img :src="item" alt="">
</div>
console.log(binding.value)
获取到后进行判断当前是否是最后一个节点,进行swiper初始化:
<div id="app">
<div class="swiper-container mySwiper">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="(item,index) in swiperList" :key="item"
v-swiper="{ current:index , length : swiperList.length }">
<img :src="item" alt="">
</div>
</div>
<div class="swiper-pagination"></div>
</div>
</div>
<script>
Vue.directive("swiper",{
inserted(el,binding){
console.log(binding.value)
if( binding.value.current === binding.value.length-1 ){
new Swiper(".mySwiper",{
loop:true,
pagination:{
el:'.swiper-pagination'
}
})
}
}
})
...
</script>
测试效果:
能够实现正常swiper的轮播以及指示器也能够呼应上,以上就是通过指令的方式来解决swiper初始化过早的问题,下面将它与之前封装的组件进行最终的合并,当然这只也是一种编写的方法,主要还是通过这种方式学习swiper封装组件的一个过程,能够启发你的思路;
封装swiper组件 3.0
下面结合组件和指令来进行swiper组件的封装,同样组件的目的不仅在于它的复用性还有灵活性,这里来简单的设置swiper能够轮播不会出现初始化和之前所讲到的种种问题,其次是可以满足使用者可以选择性的使用轮播指示器,以及轮播是否自动轮播,就这几个点来封装;
1. 编写代码
<div id="app">
<swiper>
<div class="swiper-slide" v-for="(item,index) in swiperList" :key="item"
v-swiper="{ current:index , length : swiperList.length , loop : true }">
<img :src="item" alt="">
</div>
<template #pagination>
<div class="swiper-pagination"></div>
</template>
</swiper>
</div>
<script>
Vue.directive("swiper",{
inserted(el,binding){
const baseOptions = {
loop:false,
autoplay:{
delay:2000
},
pagination:{
el:'.swiper-pagination'
}
}
const updateOptions = {
loop:binding.value.loop
}
if(binding.value.current === binding.value.length-1){
new Swiper(".mySwiper",Object.assign(baseOptions,updateOptions))
console.log(Object.assign(baseOptions,updateOptions))
}
}
})
Vue.component("swiper",{
template:`
<div class="swiper-container mySwiper">
<div class="swiper-wrapper">
<slot></slot>
</div>
<slot name="pagination"></slot>
</div>
`,
})
new Vue({
el:'#app',
data:{
swiperList:[]
},
mounted(){
// 假设请求回来的数据赋值给swiperList
this.swiperList = [
'ImageOne' ,
'ImageTwo' ,
'ImageThree' ];
// new Swiper(".author")
},2000)
}
})
</script>
2. 测试效果
以上就是本篇的内容了,本篇的前半部分自定义指令的内容如果能够理解动画,后半部分对组件的封装难度的话来理解和完成的话会比较容易些,那么在Vue中封装swiper组件的内容也就暂时到此告一段落,在此感谢大家的支持!