上一篇内容讲到封装Swiper组件的一个过程,如果是静态的数据封装组件初始化在mounted当中并无多大影响,但是这样封装的组件复用性较低或者可能只使用一次,那么在动态使用通过ajax请求数据需要面临的是swiper初始化过早的问题,在mounted生命周期中初始化会导致swiper组件的创建完成但swiper中的轮播数据还未准备好造成swiper没法轮播起来,而在updated当中做swiper的初始化能够使swiper的轮播能够正常进行,但存在的问题一旦data数据中的状态改变会引起updated中的swiper初始化重复执行,具有一定隐患,所以在updated当中是不能够进行swiper初始化工作,转而到mounted生命周期当中来,通过设置key值的方式,设置key值的这种方式是在讲这个diff算法如何进行虚拟DOM的对比,不设置key值前在mounted生命周期当中初始化是swiper为了提高用户体验和效率,保留了swiper标签只替换了swiper中的数据,如果设置key值,swiper组件前后的key比对不同,Vue会将之前的swiper删除然后重新创建,此时swiper当中的数据已经准备好了可以进行swiper初始化工作,这样一来swiper组件的封装就已经告一段落了!
以上的内容是对上一篇内容的总结回顾,那么既然已经解决了那些问题,swiper组件也能够成功的运行起来,封装组件不就到此结束了吗? 即使这样我们仍然还有一些需要进一步的发掘。先将上一篇内容的代码整理一份在这里继续讲解:
<div id="app">
<swiper :key="swiperList.length">
<div class="swiper-slide" v-for="(item,index) in swiperList" :key="index">
<img :src="item" />
</div>
</swiper>
</div>
<script>
Vue.component("swiper",{
template:`
<div>
<div class="swiper-container author" >
<div class="swiper-wrapper">
<slot></slot>
</div>
<div class="swiper-pagination"></div>
</div>
`,
mounted(){
new Swiper(".author",{
loop:true,
autoplay:{
delay:2000
},
pagination:{
el:'.swiper-pagination'
}
})
}
})
new Vue({
el:'#app',
data:{
swiperList:[] // 请求的数据容器
},
mounted(){
// 模拟发起ajax请求
setTimeout(()=>{
this.swiperList = [
'https://s2.loli.net/2022/07/18/1nMDLzF35hsYZ8t.jpg' ,
'https://s2.loli.net/2022/07/18/yFXUisGht9x5PjY.jpg' ,
'https://s2.loli.net/2022/07/18/8WhpU5EDQTySONY.jpg' ];
},2000)
}
})
</script>
" v-if " 指令
以上通过上一篇的回顾和代码可以知道的是设置key值的这套过程换一个思路就是swiper组件在创建的时候要进行mounted生命周期对swiper进行初始化,前提是swiperList已经装备好了,这样才能够让swiper轮播起来,说到这你可能会想到有一个指令好像可行,谁呢?" v-if " 指令;通过判断swiperList.length来确定swiperList是否有数据,如果有的话在创建swiper组件然后swiper组件进入mounted生命周期对swiper进行初始化,这样一来swiper组件不也可以轮播起来了吗?
1. 代码编写:
<div id="app">
<swiper v-if="swiperList.length">
<div class="swiper-slide" v-for="(item,index) in swiperList" :key="index">
<img :src="item" />
</div>
</swiper>
</div>
2. 测试效果:
通过v-if指令判断swiperList是否为真,也即是swiperList已经有数据了,此时创建swiper进入mounted生命周期进行swiper初始化,一次就能够成功!这也不失为封装组件的一个好办法!
封装Swiper组件的灵活性
封装完swiper组件后会发现当我使用的时候不需要用这个指示器(圆点),那我怎么去掉呢?显然组件好像还不够灵活,可以使用之前讲过的哪些知识点呢?就是这个插槽,通过插槽的方式,如果使用者不想要这个图片指示器的话,就可以不传指示器,让组件变得更加的灵活;
下面使用新版的slot,在讲新版本插槽的时候讲过要注意版本问题,同时要结合template标签进行包裹使用,同时还有简写,这里附上地址,回顾温习一下: 第三十一篇 v-slot 插槽使用
1. 编写代码
<div id="app">
<swiper v-if="swiperList.length">
<div class="swiper-slide" v-for="(item,index) in swiperList" :key="index">
<img :src="item" />
</div>
<!-- 使用者使用的话可以编写template的内容 -->
<template #pagination>
<div class="swiper-pagination"></div>
</template>
</swiper>
</div>
<script>
Vue.component("swiper",{
template:`
<div>
<div class="swiper-container author" >
<div class="swiper-wrapper">
<slot></slot>
</div>
<slot name="pagination"></slot>
</div>
</div>
`,
...
2. 去掉 <template> 标签的内容测试
没有对应的指示器圆点出现,那么当需要的时候可以进行编写<template>的内容;那么指示器解决了,这会我不想让它去自动轮播 (loop:true),默认是不轮播,要不要轮播让使用者自己决定,这个要怎么来解决呢?结合之前的什么内容呢? 就是这个属性,给组件传一个属性的方式,这里就结合了之前的组件通信内容,可以进行一个父传子,默认的loop值为false,将值赋给loop为true,那么顺着这个思路进行编码:
<div id="app">
<swiper v-if="swiperList.length" :options="{loop:true}">
<div class="swiper-slide" v-for="(item,index) in swiperList" :key="index">
<img :src="item" />
</div>
<template #pagination>
<div class="swiper-pagination"></div>
</template>
</swiper>
</div>
Vue.component("swiper",{
props:["options"],
template:`
<div>
<div class="swiper-container author" >
<div class="swiper-wrapper">
<slot></slot>
</div>
<slot name="pagination"></slot>
</div>
</div>
`,
mounted(){
new Swiper(".author",{
loop:false,
autoplay:{
delay:2000
},
pagination:{
el:'.swiper-pagination'
}
}),
console.log("options值",this.options);
},
...
通过props传值将使用者想开启自动轮播的值传到子组件中,即options值;测试效果:
传过来属性跟原来的对象进行合并,怎么合并进去?如何快速让两个对象合并在一起呢?
Object.assign()方法
将所可枚举的自有的属性从一个或多个源对象复制到目标对象,返回修改后的对象。
1. 下面来将其进行合并,代码编写:(修改mounted中代码)
mounted(){
var baseOptions = {
loop:false,
autoplay:{
delay:2000
},
pagination:{
el:'.swiper-pagination'
}
}
new Swiper(".author",Object.assign(baseOptions,this.options))
}
2. 测试打印一下:
console.log(baseOptions); // 预期: loop:false -> true
通过以上的这些为组件传入属性和使用插槽都能够使得组件得更加的灵活,封装一个好的组件所要具备的不单只是可复用性,还有它的灵活性,能够使使用者充分发挥。那么本篇的内容就到此结束了,那么你对Vue封装swiper组件是否已经掌握以及是否了解封装组件需要注意的内容了呢!在此感谢大家的支持!