Vue2.0生命周期的理解


Posted in Javascript onAugust 20, 2018

网上已经有很多关于vue生命周期的文章,我的这篇文章的由来,其实是我对官网上描述的一句话的思考与理解:“el被新创建的vm.$el替换”,所以文章更多的内容可能是在对vue生命周期中“created -> beforeMount -> mounted” 过程的理解。

beforeCreate --> created 之间

在这个阶段初始化事件,进行数据观测。

created

vue实例创建完后被调用,此时已经完成了数据观测(data observer),属性和方法的运算,watch/event 事件回调的配置。

可调用methods中的方法,访问和修改data中的数据,并触发响应式变化使DOM渲染更新,触发watch中相应的方法,computed相关属性进行重新计算。

一般在created时,进行ajax请求初始化实例数据。

此时,vm.$el不可见。

created --> beforeMount 之间

Vue2.0生命周期的理解

 在这个过程中,

a、首先判断实例中是否有el选项,有的话继续向下编译,没有的话会停止编译,直到vm.$mount(el)被调用时才继续(el是挂载的DOM节点);

b、接下来判断实例中是否有template,有的话将其作为模板编译成rander函数;

c、没有template的话就,就将挂载DOM元素的html(即el所对应的DOM元素及其内部的元素)提取出来作为模板编译;

*注:el所对应的DOM元素不能为body/html元素,因为在后面vue实例挂载时,el所对应的DOM元素及其内部的元素会被模板渲染出来的新的DOM所替换。

d、如果实例对象中有rander函数,就直接通过它进行渲染操作。

优先级:rander函数 > template > 外部html

此时,rander函数已经准备好并首次被调用。

在这个过程中,$el被初始化为实例中el选项所对应的DOM元素,所以在beforeMount时,用vm.$el获取到的是挂载DOM元素的html。

beforeMount

 beforeMount被调用时,此时$el可见。

beforeMount --> mounted 之间

在这个过程中,el被新创建的vm.$el所替换,并完成实例的挂载。即实例中的el选项被模板渲染创建出来的DOM元素所替换,页面中的挂载点被渲染出的vue实例代码段所替换。

Mounted

此时实例已挂载到DOM上,可以通过DOM API获取实例中DOM节点。在控制台打印vm.$el,发现之前的挂载点及内容已被替换成新的DOM。

下面通过栗子看一下这两个过程。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="https://cdn.bootcss.com/vue/2.5.13/vue.min.js"></script>
</head>
<body>
<div id="app">
  <a id='ela' href="">{{message}}</a>
</div>
</body>
<script>
  var app = new Vue({
    el: '#app',
    data: function () {
      return {
        message: 'hello'
      };
    },
    template: '<p id="elp">{{message}}</p>',
    beforeMount: function () {
      console.group('beforeMount 挂载前状态===============》');
      let state = {
        'el': this.$el,
        'data': this.$data,
        'message': this.message
      }
      let a = document.getElementById('ela');
      let p = document.getElementById('elp');
      console.log(this.$el);
      console.log(state);
      console.log(a);  // <a id='ela' href="">{{message}}</a>
      console.log(p);   // null
    },
    mounted: function () {
      console.group('mounted 挂载结束状态===============》');
      let state = {
        'el': this.$el,
        'data': this.$data,
        'message': this.message
      }
      let a = document.getElementById('ela');
      let p = document.getElementById('elp');
      console.log(this.$el);
      console.log(state);
      console.log(a);  // null
      console.log(p);   // <p id="elp">father</p>
    }
</script>
</html>

Vue2.0生命周期的理解

用template/rander选项可以在控制台清楚的看到:挂载完成后,el被新创建的vm.$el替换。

挂载前是以初始的el和虚拟DOM的形式存在的,此时以template中的内容为模板,模板内容不可见,打印p标签为null;

挂载后,模板渲染的新DOM替换原来的el,原el所对应的DOM不存在,打印a标签为null。

 beforeUpdate 和 updated

当data对象中数据更新时,会触发 beforeUpdate钩子,此时view层还没有更新。 beforeUpdate有下面几个需要注意的地方:

a、更新的数据必须在模板中直接或间接的使用,才会触发beforeUpdate;

b、在挂载之前,data中数据更新不会触发 beforeUpdate!即在created、beforeMount时改变数据不会触发更新流程;

c、如果在beforeUpdate中,再次修改了该数据的值,会再次触发beforeUpdate钩子,进行两次更新流程。

updated时,view层已更新完毕。

(在上面的代码中增加两个钩子)

mounted: function () {
  this.message = 'first';
//   this.show = false;    // 由于模板中没有用到show,所以show的改变不会触发beforeUpdate
},
beforeUpdate: function () {
  console.group('beforeUpdate 更新前状态===============》');
  let elp = document.getElementById('elp').innerHTML;
  console.log('message:' + this.message);
  console.log('DOM:' + elp);
},
updated: function () {
  console.group('updated 更新完成状态===============》');
  let elp = document.getElementById('elp').innerHTML;
  console.log('message:' + this.message);
  console.log('DOM:' + elp);
}

Vue2.0生命周期的理解

这里需要注意一点:view层我们需要通过innerHTML获取对应元素节点中的内容,而不能直接获取元素节点。直接获取元素节点,在控制台打印出来的view层中的数据都是更新之后的状态,不能打印出实时的正确的值,这应该和Chrome控制台的输出有关。

针对第三条,我们看一下下面的代码演示:

mounted: function () {
  this.message = 'first';
},
beforeUpdate: function () {
  console.group('beforeUpdate 更新前状态===============》');
  let elp = document.getElementById('elp').innerHTML;
  console.log('message:' + this.message);
  console.log('DOM:' + elp);
  this.message = 'second';  // 此时在beforeUpdate中再次修改了message的值
},
updated: function () {
  console.group('updated 更新完成状态===============》');
  let elp = document.getElementById('elp').innerHTML;
  console.log('message:' + this.message);
  console.log('DOM:' + elp);
}

Vue2.0生命周期的理解

这里我们可以清楚的看到进行了两次更新流程,但是对打印的结果有些疑问:第一次将message的值改为first,并且以first来渲染更新DOM,那么第一次调用updated时,message和DOM中的值都应该是first,而此时打印出来的时second。我理解的是,在第一次执行updated时,DOM就已经完成了第二次渲染更新,具体的过程还需要通过之后对源码的学习去理解。这里各位有不同的理解或者更详细的解释,可以在评论区留言,共同学习。

在这里,我们可以在beforeUpdate中加定时器去修改message的值,就可以等待第一次数据改变,DOM更新渲染完成后,进行第二次数据改变。

beforeUpdate: function () {
  console.group('beforeUpdate 更新前状态===============》');
  let elp = document.getElementById('elp').innerHTML;
  console.log('message:' + this.message);
  console.log('DOM:' + elp);
  var that = this;
  setTimeout(function(){
  that.message = 'second';
  });
//  this.message = 'second';  // 此时在beforeUpdate中再次修改了message的值
},

Vue2.0生命周期的理解

这里可以清楚看到两次数据改变时,数据和view层的更新状态。

beforeDestroy 和 destroyed

beforeDestroy:实例在销毁之前调用,此时实例仍然可用。

beforeDestroy -> destroyed: Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

destroyed:vue实例销毁后调用。

结尾:关于vue生命周期就总结完毕,有错误的地方烦请指出,会及时修改!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
比较简单的一个符合web标准的JS调用flash方法
Nov 29 Javascript
屏蔽Flash右键信息的js代码
Jan 17 Javascript
getJSON调用后台json数据时函数被调用两次的原因猜想
Sep 29 Javascript
JS中typeof与instanceof之间的区别总结
Nov 14 Javascript
兼容主流浏览器的jQuery+CSS 实现遮罩层的简单代码
Oct 14 Javascript
JavaScript学习笔记之JS对象
Jan 22 Javascript
javascript中callee与caller的区别分析
Apr 20 Javascript
JS数组搜索之折半搜索实现方法分析
Mar 27 Javascript
详解vue组件化开发-vuex状态管理库
Apr 10 Javascript
小程序实现左右来回滚动字幕效果
Dec 28 Javascript
JS正则表达式验证密码强度
Mar 18 Javascript
详解vue修改elementUI的分页组件视图没更新问题
Nov 13 Javascript
JavaScript作用域、闭包、对象与原型链概念及用法实例总结
Aug 20 #Javascript
RequireJS用法简单示例
Aug 20 #Javascript
JavaScript实现多态和继承的封装操作示例
Aug 20 #Javascript
浅谈微信小程序之官方UI框架we-ui使用教程
Aug 20 #Javascript
Layui给数据表格动态添加一行并跳转到添加行所在页的方法
Aug 20 #Javascript
微信小程序 MinUI组件库系列之badge徽章组件示例
Aug 20 #Javascript
获取layer.open弹出层的返回值方法
Aug 20 #Javascript
You might like
Win7 64位系统下PHP连接Oracle数据库
2014/08/20 PHP
php实现读取手机客户端浏览器的类
2015/01/09 PHP
ThinkPHP打水印及设置水印位置的方法
2016/10/14 PHP
PHP多维数组元素操作类的方法
2016/11/14 PHP
Yii框架小部件(Widgets)用法实例详解
2020/05/15 PHP
javascript 特性检测并非浏览器检测
2010/01/15 Javascript
电子商务网站上的常用的js放大镜效果
2011/12/08 Javascript
jQuery快速上手:写jQuery与直接写JS的区别详细解析
2013/08/26 Javascript
jquery遍历select元素(实例讲解)
2013/12/31 Javascript
js中window.open打开一个新的页面
2014/08/10 Javascript
ExtJs动态生成treepanel的Json格式
2015/07/19 Javascript
不间断循环滚动效果的实例代码(必看篇)
2016/10/08 Javascript
angular第三方包开发整理(小结)
2018/04/19 Javascript
快速了解Node中的Stream流是什么
2019/02/13 Javascript
简述Vue中容易被忽视的知识点
2019/12/09 Javascript
vue实现多个echarts根据屏幕大小变化而变化实例
2020/07/19 Javascript
vue中提示$index is not defined错误的解决方式
2020/09/02 Javascript
基于vue+echarts数据可视化大屏展示的实现
2020/12/25 Vue.js
[52:26]完美世界DOTA2联赛决赛 FTD vs Phoenix 第一场 11.08
2020/11/11 DOTA
简单的python后台管理程序
2017/04/13 Python
Python编程实现双击更新所有已安装python模块的方法
2017/06/05 Python
Python自定义装饰器原理与用法实例分析
2018/07/16 Python
Python list列表中删除多个重复元素操作示例
2019/02/27 Python
记录Python脚本的运行日志的方法
2019/06/05 Python
python删除文件、清空目录的实现方法
2020/09/23 Python
Delphi工程师笔试题
2013/09/21 面试题
设计部经理的岗位职责
2013/11/16 职场文书
日语专业个人的求职信
2013/12/03 职场文书
宠物店的创业计划书范文
2014/01/11 职场文书
优秀求职信范文分享
2014/01/26 职场文书
中学教师请假制度
2014/02/03 职场文书
超市国庆节促销方案
2014/02/20 职场文书
开学寄语大全
2014/04/08 职场文书
《沙漠中的绿洲》教学反思
2014/04/24 职场文书
行政专员岗位职责范本
2014/08/26 职场文书
2014年惩防体系建设工作总结
2014/12/01 职场文书