Vue学习系列(四)——理解生命周期和钩子

前言

上一篇中,我们对平时进行vue开发中遇到的常用指令进行归类说明讲解,大概已经学会了怎么去实现数据绑定,以及实现动态的实现数据展示功能,运用指令,可以更好更快的进行开发。而在这一篇中,我们将通过实例,探究vue的生命周期。

万物皆有灵,世间万物都拥有灵魂,小到山河湖海,花草树木,蚂蚁到人类,以及所有的动植物,大到地球星空和宇宙,都拥有灵魂,可以说他们都是有生命的,只是他们的生命形态是我们人类所不能理解的存在。在生产中,生命周期通俗来讲,就是从自然中来回到自然中去的全过程,也就是从采集材料设计,到加工生产后流通使用的过程,以及产品报废,进而回归大自然的过程,这整个过程就是一个完整的生命周期。因此,在开发应用项目的中,从启动页面的加载,页面渲染到销毁,也算是生命周期。Vue把整个生命周期划分为创建、挂载、更新、销毁等阶段,每个阶段都会给一些“钩子”让我们来做一些我们想实现的动作。这里的“钩子”可以这么理解,就是在每一个阶段用钩子钩住,并进行响应的操作。

学习生命周期,可以使我们更好的理解Vue的生命机制,通过了解每个阶段的钩子,可以更好的实现我们的业务代码,处理更加复杂的业务逻辑。

内容

Vue每一个组件都有属于自己的生命周期,从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等这就是一个组件的生命周期。

在整个生命周期内,总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。

执行顺序

*图片来自官网,只要你理解了这张图,也就对Vue的生命周期有了一个大致的了解。

在谈到Vue的生命周期的时候,我们首先需要创建一个实例:

开始

一、创建前/后:

1.beforeCreate-创建前 :实例创建前:这个阶段实例的data、methods是读不到的(el 和 data 并未初始化)

  var app = new Vue({
      el: ‘#app‘,
      data: {
          message : "这是艾三元的主页"
      },
       beforeCreate: function () {
                console.group(‘beforeCreate 组件刚刚被创建,组件属性计算前状态===============》‘);
               console.log("%c%s", "color:red" , "el     : " + this.$el); //undefined
               console.log("%c%s", "color:red","data   : " + this.$data); //undefined
               console.log("%c%s", "color:red","message: " + this.message)  //undefined
        },
})

2.created-创建完成 :实例创建后:这个阶段已经完成了数据观测(data observer),属性和方法的运算, watch/event 事件回调。mount挂载阶段还没开始,$el 属性目前不可见,数据并没有在DOM元素上进行渲染(完成了data数据的初始化,el没有)

 var app = new Vue({
      el: ‘#app‘,
      data: {
          message : "这是艾三元的主页"
      },
        created: function () {
            console.group(‘created 组件创建完毕,属性已经绑定但dom还未生成的状态===============》‘);
            console.log("%c%s", "color:red","el     : " + this.$el); //undefined
               console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
               console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
})

二、载入前/后

1.beforeMount :准备载入——在挂载开始之前被调用:相关的 render 函数首次被调用。程序运行,控制台看输出 (完成了虚拟el和data初始化)

  var app = new Vue({
      el: ‘#app‘,
      data: {
          message : "这是艾三元的主页"
      },
        beforeMount: function () {
            console.group(‘beforeMount 模板挂载前状态===============》‘);
            console.log("%c%s", "color:red","el     : " + (this.$el)); //已被初始化
            console.log(this.$el);
               console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
               console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
})

2.mounted :挂载完成——el选项的DOM节点 被新创建的 vm.$el 替换,并挂载到实例上去之后调用此生命周期函数。此时实例的数据在DOM节点上进行渲染(完成了真实el和data初始化)

var app = new Vue({
      el: ‘#app‘,
      data: {
          message : "这是艾三元的主页"
      },
        mounted: function () {
            console.group(‘mounted 模板挂载结束状态===============》‘);
            console.log("%c%s", "color:red","el     : " + this.$el); //已被初始化
            console.log(this.$el);
               console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
               console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
})

这个时候,页面渲染的四个阶段已经完成了,我们看看流程:(刚开始的时候beforeCreate阶段,数据和页面都没有渲染,但是页面的静态数据已经被加载出来,然后一步一步,先vue实例,然后挂载,到最后页面渲染完成)

三、更新前/后

1.beforeUpdate :更新Data之前——数据更新时调用,但不进行DOM重新渲染,在数据更新时DOM没渲染前可以在这个生命函数里进行状态处理

当修改vue实例的data时,vue就会自动帮我们更新渲染视图,在这个过程中,vue提供了beforeUpdate的钩子给我们,在检测到我们要修改数据的时候,更新渲染视图之前就会触发钩子beforeUpdate。

  var app = new Vue({
      el: ‘#app‘,
      data: {
          message : "这是艾三元的主页"
      },
        beforeUpdate: function () {
            console.group(‘beforeUpdate 更新前状态===============》‘);
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
               console.log("%c%s", "color:red","data   : " + this.$data);
               console.log("%c%s", "color:red","message: " + this.message);
        },
})

控制台输入 app.message = ‘艾三元‘

由图看来,我们的 Data 数据已经更新了,但是页面里还没有更新

2.update :这个状态下数据更新并且DOM重新渲染,当这个生命周期函数被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。当实例每次进行数据更新时updated都会执行

 var app = new Vue({
      el: ‘#app‘,
      data: {
          message : "这是艾三元的主页"
      },
        updated: function () {
            console.group(‘updated 更新完成状态===============》‘);
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
               console.log("%c%s", "color:red","data   : " + this.$data);
               console.log("%c%s", "color:red","message: " + this.message);
        },
})

四、销毁前/后

1.beforeDestroy :页面销毁前——实例销毁之前调用。调用实例的destroy( )方法可以销毁当前的组件,在销毁前,会触发beforeDestroy钩子。

  var app = new Vue({
      el: ‘#app‘,
      data: {
          message : "这是艾三元的主页"
      },
        beforeDestroy: function () {
            console.group(‘beforeDestroy 销毁前状态===============》‘);
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
               console.log("%c%s", "color:red","data   : " + this.$data);
               console.log("%c%s", "color:red","message: " + this.message);
        },
})

控制台输入 app.$destroy()

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

var app = new Vue({
      el: ‘#app‘,
      data: {
          message : "这是艾三元的主页"
      },
        destroyed: function () {
            console.group(‘destroyed 销毁完成状态===============》‘);
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
               console.log("%c%s", "color:red","data   : " + this.$data);
               console.log("%c%s", "color:red","message: " + this.message)
        }
})

这个时候我们可以看到,vue 实例被销毁后,再修改 Data 页面也已经不能修改页面 DOM 了。

源码

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/vue/2.1.3/vue.js"></script>
</head>
<body>

<div id="app">
     <p>{{ message }}</p>
</div>

<script type="text/javascript">

  var app = new Vue({
      el: ‘#app‘,
      data: {
          message : "这是艾三元的主页"
      },
        beforeCreate: function () {
           console.group(‘beforeCreate 组件刚刚被创建,组件属性计算前状态===============》‘);
           console.log("%c%s", "color:red" , "el     : " + this.$el); //undefined
           console.log("%c%s", "color:red","data   : " + this.$data); //undefined
           console.log("%c%s", "color:red","message: " + this.message)  //undefined
        },
        created: function () {
           console.group(‘created 组件创建完毕,属性已经绑定但dom还未生成的状态===============》‘);
           console.log("%c%s", "color:red","el     : " + this.$el); //undefined
           console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
           console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
        beforeMount: function () {
           console.group(‘beforeMount 模板挂载前状态===============》‘);
           console.log("%c%s", "color:red","el     : " + (this.$el)); //已被初始化
           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("%c%s", "color:red","el     : " + this.$el); //已被初始化
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
            console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
        beforeUpdate: function () {
            console.group(‘beforeUpdate 更新前状态===============》‘);
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message);
        },
        updated: function () {
            console.group(‘updated 更新完成状态===============》‘);
            console.log("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message);
        },
        beforeDestroy: function () {
            console.group(‘beforeDestroy 销毁前状态===============》‘);
            console.log("%c%s", "color:red","el     : " + this.$el);
            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("%c%s", "color:red","el     : " + this.$el);
            console.log(this.$el);
            console.log("%c%s", "color:red","data   : " + this.$data);
            console.log("%c%s", "color:red","message: " + this.message)
        }
    })
</script>
</body>
</html>

附加说明

1.说说钩子是什么时候触发的?

Vue文档源码:在实例化的时候

function Vue(opt){    

    this._init(opt)

}
Vue.prototype._init(opt){
    ... 合并选项
    ... 设置初始值 ,事件 等数据
    initLifecycle(vm)
    callHook(vm, ‘beforeCreate‘);
    ... 初始化选项等数据
    callHook(vm, ‘created‘);
    ...获取挂载的DOM 父节点
    callHook(vm, ‘beforeMount‘);
    ...解析模板成渲染函数,并执行渲染函数,生成DOM插入页面
    vm._isMounted = true;
    callHook(vm, ‘mounted‘);
}
// 组件更新时会调用这个函数
Vue.prototype._update = function(

    vnode, hydrating

) {    

    if (vm._isMounted) {

        callHook(vm, ‘beforeUpdate‘);
    }
    ...重新调用渲染函数,对比旧节点和新节点,得到最小差异,然后只更新这部分页面
    callHook(vm, ‘updated‘);
}
// 节点被移除时会调用这个函数
Vue.prototype.$destroy = function() {
    callHook(vm, ‘beforeDestroy‘);
    vm._isBeingDestroyed = true;
    ...实例被消除,移除所有 watcher
    vm._isDestroyed = true;
    ...DOM被移除
    callHook(vm, ‘destroyed‘);
}

在执行钩子的时候,会触发这个函数,遍历执行,绑定上下文

function callHook(vm, hook) {    

    // 是自己传入的 created 等回调

    var handlers = vm.$options[hook];    

    if (handlers) {        

    for (var i = 0,j = handlers.length; i < j; i++) {

            handlers[i].call(vm);
        }
    }
}

总结

1.通过简单了解 Vue 生命周期的八个阶段,可以应用在之后的开发中,针对不同的阶段的钩子采取不同的操作,更好的实现我们的业务代码,处理更加复杂的业务逻辑。

2.参考资料Vue官网

3.下一篇开始创建项目应用

原文地址:https://www.cnblogs.com/i3yuan/p/11779714.html

时间: 2024-10-03 14:15:11

Vue学习系列(四)——理解生命周期和钩子的相关文章

vue个人学习(四)----生命周期

生命周期: beforeCreate          组件实例刚刚被创建,属性都没有 created                  实例已经创建完成,属性已经绑定 beforeMount          模板编译之前 mounted               模板编译之后,代替之前ready * beforeUpdate        组件更新之前 updated               组件更新完毕 * beforeDestroy      组件销毁前 destroyed    

vue学习(1)生命周期

生命周期的概念: 什么是生命周期: Vue实例有一个完整的生命周期,这个生命周期指的是Vue实例从开始创建,初始化数据,编译模板,挂载Dom,渲染-更新-渲染,卸载等一系列的过程,我们称这是vue的生命周期, 也就是说:vue实例的生命周期是从实力创建到销毁的过程,在生命周期中,提供了一系列的函数,这些函数应用到vue生命周期的不同阶段,我们称之为生命周期钩子,生命周期钩子用来在生命周期的不同阶段来调用不同的函数 生命周期图示:

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

对于vue的生命周期,官方文档上并没有太多的文字性说明,把自己对生命周期和钩子函数的理解记录下来 官方文档 自己的理解 vue生命周期的概念:vue对象从被创建,到执行逻辑,最后到被销毁的过程. 具体流程: 1)vue实例的创建 2)初始化事件和生命周期 3)初始化data和methods 4)生成虚拟dom $el(将没有解析的指令的dom加载到内存中) 5)使用$el 来替代el,并且将$el中的指令进行解析 6)进行状态mounted的循环 判断data中的数据是否发生改变,如果改变,则跟

osgi实战学习之路:5.生命周期及利用命令、装饰者模式实现基于socket交互Bundle命令demo

生命周期中关键3个类: BundleActivator 入口点,类似main方法 BundleContext Bundle上下文对象,在运行期间,为应用程序提供操作osgi框架的方法 Bundle 代表一个已安装的Bundle 接口说明: BundleActivator: public interface BundleActivator { public void start(BundleContext context) throws Exception; public void stop(Bu

vue生命周期、钩子函数

https://segmentfault.com/a/1190000011381906    详解生命周期和钩子函数 每个vue实例再被创建之前都要经过一系列的初始化过程,这个过程就是vue的生命周期. 可以看到在vue一整个的生命周期中会有很多钩子函数提供给我们在vue生命周期不同的时刻进行操作, 那么先列出所有的钩子函数,然后我们再一一详解: beforeCreate created beforeMount mounted beforeUpdate updated beforeDestroy

Vue的过滤器,生命周期的钩子函数和使用Vue-router

一.过滤器 1.局部过滤器 在当前组件内部使用过滤器 给某些数据 添油加醋 //声明 filters:{ '过滤器的名字':function(val,a,b){ //a 就是alax ,val就是当前的数据 } } //使用 管道符 数据 | 过滤器的名字('alex','wusir') <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8">

Vue 实例详解与生命周期

Vue 实例详解与生命周期 Vue 的实例是 Vue 框架的入口,其实也就是前端的 ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个 Vue 实例生成.编译.挂着.销毁等过程进行 js 控制. Vue 实例初始化的选项配置对象详解 前面我们已经用了很多次 new Vue({...})的代码,而且 Vue 初始化的选项都已经用了data.methods.el.computedd等,估计您看到这里时,应该已经都明白了他们的作

生命周期的钩子函数

生命周期的钩子函数(写在方法的下面,一共有11个) 1.vue的整个生命周期的特定时刻,自动调用的函数 2.beforeCreate 实例创建之前调用, 数据没有挂载,不能访问数据 vue实例初始化的时候就被执行(数据加载之前执行的一个函数,拿不到data里面的数据) 3.created 实例创建之后调用,能访问.修改数据,单修改数据不会触发updated函数  在这里可以向服务器请求数据,(也可以拿到父组件的数组进行修改等操作,这一步骤是没有操作到模板,数据和模板还没有结合) 下一步就是开始找

Vue入门系列(五)Vue实例详解与生命周期

[入门系列] [本文转自] http://www.cnblogs.com/fly_dragon Vue的实例是Vue框架的入口,其实也就是前端的ViewModel,它包含了页面中的业务逻辑处理.数据模型等,当然它也有自己的一系列的生命周期的事件钩子,辅助我们进行对整个Vue实例生成.编译.挂着.销毁等过程进行js控制. 5.1. Vue实例初始化的选项配置对象详解 前面我们已经用了很多次 new Vue({...})的代码,而且Vue初始化的选项都已经用了data.methods.el.comp