Vue 的生命周期与get请求

本文将通过模拟发送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是存在的。

        扫描二维码关注公众号,回复: 10131084 查看本文章
      • 但是,我们进行异步请求的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这个钩子函数里面去。

猜你喜欢

转载自www.cnblogs.com/Welin/p/12562116.html