本文将通过模拟发送get请求使用swiper制作一个简易的banner图,结合Vue的生命周期的特点进行讲解
首先我们先进行案例的简单布局
准备一个list.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":"天天伏魔"} ]}
index.html
<link rel="stylesheet" href="https://unpkg.com/swiper/css/swiper.min.css"> <style> .swiper-container{ width: 600px; height: 300px; } </style> <body> <div id="app"> <!-- 调用模板 --> <my-banner></my-banner> </div> <!-- 创建模板 --> <template id="my-banner"> <div class="swiper-container"> <div class="swiper-wrapper"> <div class="swiper-slide" v-for="banner in banners" > <!-- v-for遍历json --> <img width="100%" :src="banner.image" alt=""> </div> </div> </div> </template> <!-- 引入swiper --> <script src="https://unpkg.com/swiper/js/swiper.min.js"> </script> <!-- 引入vue --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <!-- 引入vue-resource --> <script src="https://cdn.bootcss.com/vue-resource/1.5.0/vue-resource.min.js"></script> <script> //创建组件 Vue.component("my-banner",{ template:"#my-banner", data(){ return { banners:[] } }, }) //new一个实例 new Vue({el:"#app"}) </script> </body>
发送get请求
<script> //创建组件 Vue.component("my-banner",{ template:"#my-banner", data(){ return { banners:[] } }, // created(){ //发送 get 请求 this.$http.get("./list.json").then(res=>{ console.log(res.data.bannerList) this.banners = res.data.bannerList }) }, }) //new一个实例 new Vue({el:"#app"}) </script>
此时我们在浏览器中就能看到我们轮播图完整的架构,并且显示第一张图片
我们在使用swiper的时候,必须new一个Swiper的实例才能对调用对应的方法
new Swiper(".swiper-container",{ loop:true //点击鼠标左键,向左/右滑动,可以实现图片水平向左/右一张一张的轮播 })
通过我们在发送请求的时候,需要执行的代码都会写在一起,那么我们先尝试把Swiper的实例写在created阶段看看
<script> //创建组件 Vue.component("my-banner",{ template:"#my-banner", data(){ return { banners:[] } }, // created(){ //发送 get 请求 this.$http.get("./list.json").then(res=>{ console.log(res.data.bannerList) this.banners = res.data.bannerList new Swiper(".swiper-container",{ loop:true }) }) }, }) //new一个实例 new Vue({el:"#app"}) </script>
可这个时候出现问题了,当我们点击鼠标左键,向左/右滑动的时候,轮播图是可以实现水平方向的移动的。但是,无论怎么拖拽第一张图片,都不能正常地切换到第二张图片
当我们在created阶段,实例化Swiper的时候,最外层的swiper-container容器是存在的,也就是页面当中这个真实dom是存在的。
但是,我们进行异步请求的swiper-slide这四个真实dom是不存在的,当数据刚刚更改完,内部会生成新的虚拟dom,接着马上进行新旧虚拟dom的对比,比较出来差异后才会更新真实dom的swiper-slide的dom结构。
而新旧虚拟dom之间的对比是有时间的,而更改完数据后立马进行实例化操作,等虚拟dom更新完毕后生成真实的dom结构,其实实例化Swiper操作已经提前结束完毕了。
也就是说,我们实例化Swiper的操作太快了,远快过真实dom
既然created阶段不行,那么我们就再试试beforeMount阶段
<script> //创建组件 Vue.component("my-banner",{ template:"#my-banner", data(){ return { banners:[] } }, // created(){ //发送 get 请求 this.$http.get("./list.json").then(res=>{ console.log(res.data.bannerList) this.banners = res.data.bannerList }) }, beforeMount(){ new Swiper(".swiper-container",{ loop:true }) } }) //new一个实例 new Vue({el:"#app"}) </script>
beforeMount阶段又失败了,因为beforeMount这个钩子函数压根是获取不到真实dom的结构,根本不可能获取到swiper-container
那再试试mounted阶段吧,实例化的相关操作都是在这里进行
<script> //创建组件 Vue.component("my-banner",{ template:"#my-banner", data(){ return { banners:[] } }, // created(){ //发送 get 请求 this.$http.get("./list.json").then(res=>{ console.log(res.data.bannerList) this.banners = res.data.bannerList }) }, mounted(){ new Swiper(".swiper-container",{ loop:true }) } }) //new一个实例 new Vue({el:"#app"}) </script>
然而效果还是会跟created阶段一样,拽不动
这里出现问题的主要原因在于,发送请求都是异步的代码。也就说当内部的异步请求,一边去进行请求数据的同时,下面的mounted钩子函数也正在执行,当数据回来进行进行更改操作,其实这个实例化操作早就结束了。
还是那句话,我们实例化Swiper的操作太快了,远快过真实dom
那beforeUpdate阶段总行了吧,毕竟dom挂载完毕,我们再试试
<script> //创建组件 Vue.component("my-banner",{ template:"#my-banner", data(){ return { banners:[] } }, // created(){ //发送 get 请求 this.$http.get("./list.json").then(res=>{ console.log(res.data.bannerList) this.banners = res.data.bannerList }) }, beforeUpdate(){ new Swiper(".swiper-container",{ loop:true }) } }) //new一个实例 new Vue({el:"#app"}) </script>
然后又悲剧了,效果还是跟created阶段一样
原因是因为:当dom挂载完毕的时候,当数据发生改变的时候,beforeUpdate会立马执行!
还是老毛病,我们实例化Swiper的操作太快了,远快过真实dom
只剩最后一个updated阶段
<script> //创建组件 Vue.component("my-banner",{ template:"#my-banner", data(){ return { banners:[] } }, // created(){ //发送 get 请求 this.$http.get("./list.json").then(res=>{ console.log(res.data.bannerList) this.banners = res.data.bannerList }) }, updated(){ new Swiper(".swiper-container",{ loop:true }) } }) //new一个实例 new Vue({el:"#app"}) </script>
updated阶段可以了!!!
当数据发生改变的时候,引发虚拟dom的对比,虚拟dom对比完成后,再去渲染真实的dom结构,当真实的dom结构渲染完成后,内部才会执行updated钩子函数
说白了,数据改变了,然后swiper-slide这几个真实dom生成好了之后,才会进入到updated这个钩子函数里面去。
原文:https://www.cnblogs.com/Welin/p/12562116.html