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 相关文章推荐
Javascript Jquery 遍历Json的实现代码
Mar 31 Javascript
在JavaScript中监听IME键盘输入事件
May 29 Javascript
一些有用的JavaScript和jQuery的片段分享
Aug 23 Javascript
为什么Node.js会这么火呢?Node.js流行的原因
Dec 01 Javascript
JQuery中基础过滤选择器用法实例分析
May 18 Javascript
让html元素随浏览器的大小自适应垂直居中的实现方法
Oct 12 Javascript
JS中闭包的经典用法小结(2则示例)
Dec 28 Javascript
利用JS如何计算字符串所占字节数示例代码
Sep 13 Javascript
解决option标签selected=&quot;selected&quot;属性失效的问题
Nov 06 Javascript
JavaScript继承定义与用法实践分析
May 28 Javascript
vue中实现拖动调整左右两侧div的宽度的示例代码
Jul 22 Javascript
详解JavaScript的计时器和按钮效果设置
Feb 18 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
无线电波是什么?它是怎样传输的?
2021/03/01 无线电
Linux下CoreSeek及PHP扩展模块的安装
2012/09/23 PHP
vs2003 js文件编码问题的解决方法
2010/03/20 Javascript
js 获取Listbox选择的值的代码
2010/04/15 Javascript
收集的一些Array及String原型对象的扩展实现代码
2010/12/05 Javascript
获得所有表单值的JQuery实现代码[IE暂不支持]
2012/05/24 Javascript
javascript 快速排序函数代码
2012/05/30 Javascript
当某个文本框成为焦点时即清除文本框内容
2014/04/28 Javascript
jQuery插件pagewalkthrough实现引导页效果
2015/07/05 Javascript
nodejs创建web服务器之hello world程序
2015/08/20 NodeJs
总结十个Angular.js由浅入深的面试问题
2016/08/26 Javascript
纯JavaScript 实现flappy bird小游戏实例代码
2016/09/27 Javascript
老生常谈javascript的类型转换
2016/10/12 Javascript
jQuery编写textarea输入字数限制代码
2017/03/23 jQuery
vue-cli如何添加less 以及sass
2017/07/06 Javascript
dropload.js插件下拉刷新和上拉加载使用详解
2017/10/20 Javascript
vue 解决addRoutes动态添加路由后刷新失效问题
2018/07/02 Javascript
如何检查一个对象是否为空
2019/04/11 Javascript
详解vuex持久化插件解决浏览器刷新数据消失问题
2019/04/15 Javascript
对TypeScript库进行单元测试的方法
2019/07/18 Javascript
vue + node如何通过一个Txt文件批量生成MP3并压缩成Zip
2020/06/02 Javascript
[05:09]2016国际邀请赛中国区预选赛淘汰赛首日精彩回顾
2016/06/29 DOTA
详解python使用Nginx和uWSGI来运行Python应用
2018/01/09 Python
python实现log日志的示例代码
2018/04/28 Python
django中模板的html自动转意方法
2018/05/27 Python
OpenCV 之按位运算举例解析
2020/06/19 Python
20行代码教你用python给证件照换底色的方法示例
2021/02/05 Python
在线学习西班牙语、法语或其他语言:Babbel.com
2018/02/07 全球购物
Java语言程序设计测试题改错题部分
2014/07/22 面试题
财务管理个人自荐书范文
2013/11/24 职场文书
服务生自我鉴定
2014/01/22 职场文书
小学防溺水制度
2014/01/29 职场文书
考试作弊检讨书范文
2015/01/27 职场文书
店铺转让协议书
2015/01/29 职场文书
Redis模仿手机验证码发送的实现示例
2021/11/02 Redis
彻底弄懂Python中的回调函数(callback)
2022/06/25 Python