理解vue实例的生命周期和钩子函数

先来一张生命周期的官方图:
在这里插入图片描述
钩子函数 描述
beforeCreate 组件实例刚被创建,组件属性计算之前,如data属性等
created 组件实例创建完成,属性已绑定,但DOM还未生成,$el属性还不存在
beforeMount 模板编译 / 挂载之前
mounted 模板编译 / 挂载之后
beforeUpdate 组件更新之前
update 组件更新之后
beforeDestory 组件销毁前调用
destoryed 组件销毁后调用

用代码的形式来更深入的理解各个钩子函数的区别:
 Vue.component("my-content", {
            template: "#my-content",
            data() {
                return {
                    msg: 1
                }
            },
            methods:{
                destroy(){
                    this.$destroy()//组件被销毁
                }
            },        
            beforeCreate(){
                console.log("beforeCreate......");
                console.log(this.msg,document.getElementById("title"));                            
            },      
            created(){
                console.log("create..........");
                this.timer = setInterval(()=>{
                    console.log(111111);               
                    this.msg ++
                },3000)
                console.log(this.msg,document.getElementById("title"));                           
            },        
            beforeMount(){
                console.log("beforeMount..........");
                console.log(this.msg,document.getElementById("title"));                            
            },           
            mounted(){
                console.log("mounted........");
                console.log(this.msg,document.getElementById("title"));                    
            },         
            beforeUpdate(){
                // console.log("beforeUpdate......",this.msg);             
                console.log("beforeUpdate......",document.getElementById("title").innerHTML);              
            },          
            updated(){
                // console.log("update......",this.msg);    
                console.log("updated......",document.getElementById("title").innerHTML);        
            },          
            beforeDestroy(){
                //清除定时器
                clearInterval(this.timer)
                console.log(" beforeDestroy.......");           
            },          
            destroyed(){
                console.log("destroy........");
                
            }
        })

        new Vue({}).$mount("#app");
1-1.beforeCreate

实例、组件通过new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate钩子函数,这个时候,数据还没有挂载到,只是一个空壳,无法访问到数据和真实的dom,一般不做操作,同时页面中的真实dom节点叶没有挂载出来,null
在这里插入图片描述

1-2.created

created钩子函数内部的数据已经被挂载了,但是真实dom节点还是没有渲染出来在这个钩子函数里面,如果同步的去更改数据的话,运行中钩子函数是不会执行的。通常会在此钩子函数里面进入ajax的异步操作,另外还可以做一些初始化事件的绑定
在这里插入图片描述

1-3.beforeMount

beforeMount代表dom马上就要被渲染出来了,但是还没有真正的在页面中渲染出来,此钩子函数与created钩子函数基本一致,可以做ajax与初始化事件的绑定操作
在这里插入图片描述

1-4.mounted

数据已经挂载完毕了,真实的dom也已经渲染出来了
在这里插入图片描述

2-1. beforeUpdate

组件更新之前执行的函数,只有数据更新后,才能调用(触发)beforeUpdate,注意:此数据一定是在模板上出现的数据,否则,不会,也没有必要触发组件更新(因为数据不出现在模板里,就没有必要再次渲染),数据更新了,但是,vue(组件)对象对应的dom中的内部(innerHTML)没有变,所以叫作组件更新前
在这里插入图片描述

2-2.updated

组件更新之后执行的函数,vue(组件)对象对应的dom中的内部(innerHTML)改变了,所以,叫作组件更新之后
在这里插入图片描述

3-1. beforeDestroy

当组件销毁的时候,就会触发执行 vm.$destroyed()的时候,组件就会被销毁

3-2.destroyed

组件一但被销毁,组件的dom结构还是存在的

4.下面我们通过一个轮播图的案例来看看实际的应用

html代码:

  <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">
                    <img width="100%" :src="banner.image" alt="">
                </div>
            </div>
        </div>
    </template>

js代码:

<script src="./base/swiper.min.js"></script>
    <script src="./base/vue.js"></script>
    <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: []
                }
            },
            created() {
                this.$http.get("./banners.json").then(res => {
                    console.log(res.data.bannerList)
                    this.banners = res.data.bannerList
                    new Swiper(".swiper-container", {
                        loop: true
                    })
                })
            },     
        new Vue({
            el: "#app"
        })
    </script> 

1.此时发现了个问题,轮播图是可以滚动的,但是为啥划不过去?
原因是因为在这里实例化的时候,最外层的swiper-container容器是存在的,也就是页面当中这个真实dom是存在的而我们进行异步请求的swiper-slide这四个真实dom是不存在的,当数据刚刚更改完,内部会生成新的虚拟dom,然后 新的虚拟dom与旧的虚拟dom结构会进行对比,比较出来差异后才会更新真实dom的swiper-slide的dom结构而虚拟dom之间的对比是有时间的,而更改完数据后立马进行实例化操作,等虚拟dom更新完毕后生成真实的dom结构,其实实例化操作已经提前结束完毕了。

2.下面继续来看:

<script src="./base/swiper.min.js"></script>
    <script src="./base/vue.js"></script>
    <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: []
                }
            },
     	  created() {
                this.$http.get("./banners.json").then(res => { //1000s之后
                    console.log(res.data.bannerList)
                    this.banners = res.data.bannerList

                    
                })
            },
         
            beforeMount(){
                new Swiper(".swiper-container",{
                    loop:true 
                }
        new Vue({
            el: "#app"
        })
    </script>

发现这个钩子函数不行!因为这个钩子函数压根是获取不到真实dom的结构。

   <script src="./base/swiper.min.js"></script>
    <script src="./base/vue.js"></script>
    <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: []
                }
            },
              created() {
                this.$http.get("./banners.json").then(res => { //1000s之后
                    console.log(res.data.bannerList)
                    this.banners = res.data.bannerList

                    
                })
            },
         
            mounted(){
              new Swiper(".swiper-container",{
                  loop:true 
             })
      }    
        new Vue({
            el: "#app"
        })

发现这个钩子函数也不行!因为上面是异步的过程,他不会阻止后续mounted的相关操作。内部的异步请求边去进行请求数据的同时,下面的mounted钩子函数也正在执行,当数据回来进行进行更改操作,其实这个实例化操作早就结束了。

   <script src="./base/swiper.min.js"></script>
    <script src="./base/vue.js"></script>
    <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: []
                }
            },
            created() {
                this.$http.get("./banners.json").then(res => { //1000s之后
                    console.log(res.data.bannerList)
                    this.banners = res.data.bannerList

                    
                })
            },                  
             updated() {
                new Swiper(".swiper-container", {
                   loop: true
                 })
          }
        })
        new Vue({
            el: "#app"
        })
    </script>

这个钩子函数是可行的,当数据发生改变的时候,引发虚拟dom的对比,虚拟dom对比完成后,再去渲染真实的dom结构当真实的dom结构渲染完成后,内部才会执行updated钩子函数,数据改变了,然后swiper-slide这几个真实dom生成好了之后,才会进入到updated这个钩子函数里面去。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值