Vue入门06——利用swiper和$.nextTick制作滚动条
swiper中文网
有关于nextTick的使用,先参考其他大佬的文章,以后会对nextTick进行探究>>(链接)
引入的样式
<link rel="stylesheet" href="/base/swiper.min.css">
<script src="/base/swiper.min.js"></script>
<script src="/base/vue.js"></script>
<script src="https://cdn.bootcss.com/vue-resource/1.3.4/vue-resource.min.js"></script>
通过swiper官方文档我们知道要制作滚动条的模板格式
swiper-container → swiper-wrapper → swiper-slide
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">
<img src="" alt="">
</div>
</div>
</div>
当我们想要在多个地方使用这个模板的时候,我们可以把它封装成一个组件来使用,减少代码重复量。
把上面的格式声明成组件:
<template id="my-banner">
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">
<img src="" alt="">
</div>
</div>
</div>
</template>
<script>
Vue.component("my-banner",{
template:"#my-banner"
})
new Vue({
el:"#app"
})
</script>
因为我们的banner图需要后端来给我们传递数据,这里使用一个本地的banners.json文件来模拟获取数据
{"bannerList":
[{"id":"614","image":"http:\/\/game.dolapocket.com\/img\/banner\/20160530153840_789.jpg","url":"","imageName":"大侠归来"},
{"id":"616","image":"http:\/\/game.dolapocket.com\/img\/banner\/20160530153831_276.jpg","url":"","imageName":"暗黑之王"},
{"id":"646","image":"http:\/\/game.dolapocket.com\/img\/banner\/20160530153905_943.jpg","url":"","imageName":"大大大掌门"},
{"id":"633","image":"http:\/\/game.dolapocket.com\/img\/banner\/20160530153816_781.jpg","url":"","imageName":"天天伏魔"}]}
组件的声明周期中,created钩子函数就能获取到组件的数据,因此我们可以在created钩子函数中将获取到的添加到组件的数据中
Vue中可以使用上面引用的vue-resource中的$http.get()方法来获取数据,将获取到的数据添加到组件的数据中
<script>
Vue.component("my-banner",{
template:"#my-banner",
data(){
return{
banners:null // 一会通过数据加载来更改数据
}
},
created(){//created钩子函数,可以获取到数据
this.$http.get("./banner.json",res=>{
this.banners = res.body.bannerList
})
}
})
new Vue({
el:"#app"
})
</script>
现在组件有数据了,将数据添加到组件模板中
并对Swiper进行实例化
<div id="app">
<my-swiper></my-swiper>
</div>
<template id="my-swiper">
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="banner in banners" :key="banner.id">
<img width="100%" :src="banner.image" alt="">
</div>
</div>
</div>
</template>
<script>
Vue.component("my-banner",{
template:"#my-banner",
data(){
return{
banners:null
}
},
created(){//created钩子函数,可以获取到数据
this.$http.get("./banner.json",res=>{
this.banners = res.body.bannerList
//一切准备就绪后需要实例化一下Swiper
new Swiper(".swiper-container",{
//配置项
loop:true//无限循环
})
})
}
})
new Vue({
el:"#app"
})
</script>
但是这种方式会发现一个问题,banner能滑,但是滑不过去,这是为什么呢?
这里实例化的时候,最外层的swiper-container是存在的,但是还没有我们需要的swiper-slide这个真实的dom结构,这是因为我们改变数据的时候内部生成新的虚拟dom,新的虚拟dom和之前的虚拟dom进行对比,对比出差异后再去进行真实dom的渲染操作。
但是我们在这里瞬间完成了对Swiper实例化的操作,就导致虚拟dom对比完成生成真实的swiper-slide时,swiper的实例化操作早就结束了。
解决方案
因为数据改变引发虚拟dom更新操作,更新完成后才会生成4个swiper-slide新的真实dom,所以后续的实例化过程,必须要等因数据更新生成的4个swiper-slide渲染完成之后,再去实例化操作,就可以解决滑不动的问题。
在Vue中提供了一个nextTick方法 >> this.$nextTick(()=>{}) 这个方法规定了,在此回调函数内部,就可以获取到因数据更新而生成的新的真实dom,所以在这里进行实例化就不会导致上面发生的问题
<div id="app">
<my-swiper></my-swiper>
</div>
<template id="my-swiper">
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide" v-for="banner in banners" :key="banner.id">
<img width="100%" :src="banner.image" alt="">
</div>
</div>
</div>
</template>
<script>
Vue.component("my-banner",{
template:"#my-banner",
data(){
return{
banners:null
}
},
created(){
this.$http.get("./banners.json",res=>{
this.banners = res.body.bannerList
this.$nextTick(()=>{
new Swiper(".swiper-container",{
//配置项
loop:true
})
})
})
}
})
new Vue({
el:"#app"
})
</script>
通过this.$nextTick(()=>{}) 就解决了 更改数据时,虚拟dom对比并渲染完时,Swiper的实例化早已完成的问题。