zoukankan      html  css  js  c++  java
  • Vue----生命周期

     每个Vue实例在被创建之前都要经过一系列的初始化过程,这个过程就是vue的生命周期。

     首先贴一张Vue文档给出的生命周期图示,并添加了一些注释:

     Vue2.0的生命周期钩子一共有10个,同样结合官方文档作出了下表

    生命周期钩子函数                             调用时间
    beforeCreate 在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
    created 实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
    beforeMount 在挂载开始之前被调用:相关的 render 函数首次被调用。
    mounted el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
    beforeUpdate 数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
    updated 由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。
    activated keep-alive 组件激活时调用。
    deactivated keep-alive 组件停用时调用。
    beforeDestroy 实例销毁之前调用。在这一步,实例仍然完全可用。
    destroyed

    Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

    (除了beforeCreate和created钩子之外,其他钩子均在服务器端渲染期间不被调用。)

    一、实际操作

      我们来可视化的观察一下生命周期钩子函数执行时状态变化的情况

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <p>{{message}}</p>
        <keep-alive>
            <my-components msg="hello" v-if="show"></my-components>
        </keep-alive>
    </div>
    </body>
    <script>
        var child = {
            template: '<div>from child: {{msg}}</div>',
            props: ['msg'],
            data: function () {
                return {
                    childMsg: 'child'
                };
            },
            deactivated: function () {
                console.log('component deactivated!');
            },
            activated: function () {
                console.log('component activated');
            }
        };
        var app = new Vue({
            el: '#app',
            data: function () {
                return {
                    message: 'father',
                    show: true
                };
            },
            beforeCreate: function () {
                console.group('beforeCreate 创建前状态===============》');
                var state = {
                    'el': this.$el,
                    'data': this.$data,
                    'message': this.message
                }
                console.log(state);
            },
            created: function () {
                console.group('created 创建完毕状态===============》');
                var state = {
                    'el': this.$el,
                    'data': this.$data,
                    'message': this.message
                }
                console.log(state);
            },
            beforeMount: function () {
                console.group('beforeMount 挂载前状态===============》');
                var state = {
                    'el': this.$el,
                    'data': this.$data,
                    'message': this.message
                }
                console.log(this.$el);
                console.log(state);
            },
            mounted: function () {
                console.group('mounted 挂载结束状态===============》');
                var state = {
                    'el': this.$el,
                    'data': this.$data,
                    'message': this.message
                }
                console.log(this.$el);
                console.log(state);
            },
            beforeUpdate: function () {
                console.group('beforeUpdate 更新前状态===============》');
                var state = {
                    'el': this.$el,
                    'data': this.$data,
                    'message': this.message
                }
                console.log(this.$el);
                console.log(state);
                console.log('beforeUpdate == ' + document.getElementsByTagName('p')[0].innerHTML);
            },
            updated: function () {
                console.group('updated 更新完成状态===============》');
                var state = {
                    'el': this.$el,
                    'data': this.$data,
                    'message': this.message
                }
                console.log(this.$el);
                console.log(state);
                console.log('updated == ' + document.getElementsByTagName('p')[0].innerHTML);
            },
            beforeDestroy: function () {
                console.group('beforeDestroy 销毁前状态===============》');
                var state = {
                    'el': this.$el,
                    'data': this.$data,
                    'message': this.message
                }
                console.log(this.$el);
                console.log(state);
            },
            destroyed: function () {
                console.group('destroyed 销毁完成状态===============》');
                var state = {
                    'el': this.$el,
                    'data': this.$data,
                    'message': this.message
                }
                console.log(this.$el);
                console.log(state);
            },
            components: {
                'my-components': child
            }
        });
    </script>
    </html>

    首先来梳理一下结构:

      (1)我们创建了一个Vue根实例命名为app,将其挂载到页面id为app的dom元素上。

      (2)局部注册的一个组件child并在根实例中将其注册使其可以在根实例的作用域中使用。

      (3)将子组件用<keep-alive> 包裹,为接下来的测试作准备。在谷歌浏览器打开开发者工具,开始测试!

    1、create 和 mounted 相关

    根据打印结果:

      1、beforeCreate执行时:data和el均未初始化,值为undefined

      2、created执行时:Vue 实例观察的数据对象data已经配置好,已经可以得到app.message的值,但Vue 实例使用的根 DOM 元素el还未初始化

      3、beforeMount执行时:data和el均已经初始化,但从{{message}}等现象可以看出此时el并没有渲染进数据el的值为“虚拟”的元素节点

      4、mounted执行时:此时el已经渲染完成并挂载到实例

    beforecreated:el 和 data 并未初始化 ;created:完成了 data 数据的初始化,el没有;beforeMount:完成了 el 和 data 初始化 ;mounted :完成挂载。(注意:在beforeMount阶段应用的 Virtual DOM(虚拟Dom)技术,先把坑占住了,到后面mounted挂载的时候再把值渲染进去。)

    2、activated 和 destroyed相关

    在前面的测试图中,我们发现了activated周期钩子已经被触发,这是因为子组件my-components被<keep-alive> 包裹,随el的挂载触发。

      现在我们将此组件停用进行测试:由于子组件具有一个v-if指令v-if="show",因此我们可以通过将show的值置为false将其销毁。控制台输入 app.show = false;测试结果如下:

    由于在这里我们修改了data的值,所以会触发beforeUpdate和updated钩子,这里先不讨论这一组钩子,我们看到deactivated钩子已经触发,表示<keep-alive>已经停用,符合预期结果。

    在使用vue-router时有时需要使用<keep-alive></keep-alive>来缓存组件状态,这个时候created钩子就不会被重复调用了,如果我们的子组件需要在每次加载的时候进行某些操作,可以使用activated钩子触发。

    现在我们对Vue实例进行销毁,调用app.$destroy()方法即可将其销毁,控制台测试如下:

     我们发现实例依然存在,但是此时变化已经发生在了其他地方,根据官方文档描述:Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁

     这里我们将data中的message属性改成了'message',发现dom并没有进行相应的响应,这证实了之前的说法。同样,如果你在子组件也加入destroyed钩子,发现该钩子也会被触发,这也证明了子实例也会被一起销毁。这里的销毁并不指代'抹去',而是表示'解绑'。

    3、updated相关

      beforeUpdate和updated是最后一对周期钩子了。

    我们发现beforeUpdate和updated触发时,el中的数据都已经渲染完成,但根据beforeUpdate == father而updated == message可知,只有updated钩子被调用时候,组件dom才被更新。

    在beforeUpdate可以监听到data的变化,但是view层没有被重新渲染,view层的数据没有变化。等到updated的时候,view层才被重新渲染,数据更新。

  • 相关阅读:
    POJ1239
    HDU 2829 四边形不等式优化
    返回数字二进制的最高位位数o(n)
    矩阵快速幂 模板
    HDU4718 The LCIS on the Tree(LCT)
    HDU4010 Query on The Trees(LCT)
    HDU3487 Play With Chains(Splay)
    CF444C DZY Loves Colors
    HDU4836 The Query on the Tree(树状数组&&LCA)
    HDU4831&&4832&&4834
  • 原文地址:https://www.cnblogs.com/humiao-0626/p/11857128.html
Copyright © 2011-2022 走看看