学习章 - 记vue生命周期理解

222 阅读3分钟

最近搞了搞vue的生命周期,所以记一下自己的一些理解。首先上图:

实验代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>vue生命周期探索</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>{{message}}</h1>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'Vue的生命周期'
        },
        methods:{
            init(){
                console.log('这是一个方法!')
            }
        }
    })
</script>
</html>

一. 创建

1. 创建前 - beforeCreate

代码:

    beforeCreate: function() {
        console.group('------beforeCreate创建前状态------');
        console.log("%c%s", "color:red" , "el     : " + this.$el);
        console.log("%c%s", "color:red","data   : " + this.$data);
        console.log("%c%s", "color:red","message: " + this.message)
        console.log("%c%s", "color:red","methods   : " + this.init);
    }

执行结果:

结论: 在vue实例创建前,无法访问到 el 属性和 data 属性等。

2. 创建时

(1). 数据观测: 向 Vue 的响应式系统中加入了其 data 对象中能找到的所有属性

利用 es5 特性 Object.defineProperty,遍历data对象下所有属性,将其转化为getter/setter,以便拦截对象赋值与取值操作,然后利用发布/订阅者模式,从而实现数据的双向绑定!

(2). 初始化事件: 将methods 下的所有方法进行声明

3.创建后 - created

代码:(注释掉el选项,防止其他生命周期影响)

   // el: '#app',
    created: function() {
        console.group('------created创建完毕状态------');
        console.log("%c%s", "color:red","el     : " + this.$el);
        console.log("%c%s", "color:red","data   : " + this.$data);
        console.log("%c%s", "color:red","message: " + this.message);
        console.log("%c%s", "color:red","methods   : " + this.init);
    },

执行结果:

结论:数据已经和data属性绑定,但 $el 属性还不存在,数据未在页面显示

二. 挂载

1. 挂载前 - beforeMount

(1). 判断el选项是否存在;如果有的话就继续向下编译,如果没有el选项,则停止编译,也就意味着停止了生命周期,直到在该vue实例上调用vm.$mount(el)。

(2). 确定挂载模板;模板的产生主要有三种:render函数,template选项,外部HTML(即el所指元素)。且优先级为:render函数>template选项>外部HTML(即el所指元素)

2. 挂载后 - mounted

将确定的挂载模板替换虚拟DOM,将数据渲染到真实dom

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>vue生命周期探索</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>{{message}}</h1>
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            message: 'Vue的生命周期'
        },
        template: "<h1>{{message +'----这是在template中的'}}</h1>",
        // render: function(createElement) {
        //     return createElement('h1', 'this is createElement')
        // },
        methods:{
            init(){
                console.log('这是一个方法!')
            }
        },
        beforeMount: function() {
            console.group('------beforeMount挂载前状态------');
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message);
        },
        mounted: function() {
            console.group('------mounted 挂载结束状态------');
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message);
        }
    })
</script>
</html>

确定的挂载模板为template选项,虚拟DOM为外部HTML 执行结果:

结论: beforeMount阶段是虚拟DOM,且未对数据进行渲染。到了mounted阶段才是真实的DOM,且数据渲染

三. 更新

1. 更新前 - beforeUpdate

代码:

    beforeUpdate: function () {
        console.group('beforeUpdate 更新前状态===============》');
        console.log(this.$el.innerHTML);
        console.log("%c%s", "color:red","message: " + this.message);
    },

控制台输入 vm.message = '触发组件更新'

执行结果:

结论:可以监听到data的变化,但是view层没有被重新渲染,数据没有变化,并且是修改data的最后时机

变化前修改message:

    beforeUpdate: function () {
        console.log(this.$el.innerHTML);
        this.message = '我又改回来了,嘿嘿!'
        console.log("%c%s", "color:red","message: " + this.message);
    },

执行结果:

2. 更新后 - updated

重新渲染虚拟 dom,并通过 diff 算法对比 vnode 节点差异更新真实 dom 代码:

   updated: function () {
        console.group('updated 更新完成状态===============》');
        console.log(this.$el);
        console.log("%c%s", "color:red","message: " + this.message);
    },

执行结果:

四. 销毁

1. 销毁前 - beforeDestroy

实例还在,还是可以调用的

2. 销毁后 - destroyed

实例销毁后,Vue 实例的所有东西都会解除绑定,所有的事件监听器会被移除,所有的子实例也会被销毁,dom 和属性方法虽然都还存在,但改变他们将不再生效!

代码:

    beforeDestroy: function () {
        console.group('beforeDestroy 销毁前状态===============》');
        console.log(this.$el);
        console.log("%c%s", "color:red","data   : " + this.$data);
        console.log("%c%s", "color:red","message: " + this.message);
    },
    destroyed: function () {
        console.group('destroyed 销毁完成状态===============》');
        console.log(this.$el);
        console.log("%c%s", "color:red","data   : " + this.$data);
        console.log("%c%s", "color:red","message: " + this.message)
    }

控制台输入: vm.$destroy()

执行结果:

执行销毁后,再更新,无效!

以上是自己对vue生命周期的理解,欢迎小伙伴们一起探讨指教。

参考:

segmentfault.com/a/119000001…

www.imooc.com/article/228…