一、背景阐述
最近有人在讨论vue项目中swiper插件引用不当无效的问题,直观的问题效果是vue项目中异步请求回来的数据在swiper轮播图里显示正常却无法正常轮播,这也算是一个比较经典的问题了,官方文档对此也没有明确的解答,这里统一分析并总结一下。(本文针对vue项目)
二、分析
1.上面的图是项目中引用的swiper库(swiper中文网),这个库还算不错,不局限于vue项目,许多项目中都能够使用,毕竟人是专门做swiper轮播图的,而该插件使用一个必要的步骤就是进行初始化,不初始化或初始化过早都会导致问题。
2.在实际开发中,我们一般都是对引入的swiper进行封装,在封装的组件里留下slot插槽,以便更好复用,但这样带来的一个直接问题就是如果swiper里要轮播的数据是通过后台请求回来的,那很容易出现初始化过早。
3.前端常用的ajax请求以及第三方封装的axios请求等都是异步执行的,一般我们把swiper初始化放在mounted生命周期中进行,这导致可能请求还没拿到数据时,swiper就已经完成了初始化。即使最后拿到了数据并完成了渲染,swiper也不可能正常工作。
注:1.swiper里的数据是异步动态获取的
2.swiper初始化放在mounted或之前的生命周期中进行
只要满足上面两个条件,那一定会出现初始化过早问题
三、解决方案
1.把swiper初始化放在updated生命周期中
updated(){
new Swiper ('.swiper-container', {
loop: true,
autoplay: true,
pagination: {
el: '.swiper-pagination',
}
})
}
分析:swiper在数据取回来之前就完成了初始化,此时它初始化的是空内容,当异步请求拿到数据后再进行一次初始化,问题解决。
(有效,但不推荐。因为这可能意味着一旦轮播图里的内容改变,都会执行一次updated函数,这显然不合理)
2.为封装的组件设置key值
<myswiper :key='datalist.length'>
<div class="swiper-slide" v-for='data in datalist'>
<img :src="data.poster">
</div>
</myswiper>
分析:例为封装的组件设置key值为datalist.length之后,在异步请求拿到数据后由于datalist值变化了,会再进行一次初始化(vue的diff算法与虚拟DOM),尽管此前已经进行了一次无效的初始化。
3.在wacth监听器中初始化
分析:与上面类似
四、总结
注:1.swiper里的数据是异步动态获取的
2.swiper初始化放在mounted或之前的生命周期中进行
只要满足上面两个条件,那很可能会出现swiper初始化过早问题