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 相关文章推荐
跨浏览器开发经验总结(三)   警惕“IE依赖综合症”
May 13 Javascript
javascript正则表达式中参数g(全局)的作用
Nov 11 Javascript
js 利用image对象实现图片的预加载提高访问速度
Mar 29 Javascript
探讨JQUERY JSON的反序列化类 using问题的解决方法
Dec 19 Javascript
jquery制作 随机弹跳的小球特效
Feb 01 Javascript
在父页面得到zTree已选中的节点的方法
Feb 12 Javascript
详解jQuery中的empty、remove和detach
Apr 11 Javascript
Javascript打印局部页面实例
Jun 21 Javascript
JavaScript函数表达式详解及实例
May 05 Javascript
Vue.js结合Ueditor富文本编辑器的实例代码
Jul 11 Javascript
react 创建单例组件的方法
Apr 26 Javascript
jQuery 函数实例分析【函数声明、函数表达式、匿名函数等】
May 19 jQuery
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
PHP MVC框架skymvc支持多文件上传
2016/05/26 PHP
PHP中通过getopt解析GNU C风格命令行选项
2019/11/18 PHP
用js做一个小游戏平台 (一)
2009/12/29 Javascript
js中document.write的那点事
2014/12/12 Javascript
Javascript递归打印Document层次关系实例分析
2015/05/15 Javascript
jQuery实现鼠标滑过点击事件音效试听
2015/08/31 Javascript
Jquery中request和request.form和request.querystring的区别
2015/11/26 Javascript
JavaScript中获取纯正的undefined的方法
2016/03/06 Javascript
微信小程序 欢迎页面的制作(源码下载)
2017/01/09 Javascript
JavaScript省市级联下拉菜单实例
2017/02/14 Javascript
详解node中创建服务进程
2017/05/09 Javascript
详解Vue-cli 创建的项目如何跨域请求
2017/05/18 Javascript
使用angular帮你实现拖拽的示例
2017/07/05 Javascript
json2.js 入门教程之使用方法与实例分析
2017/09/14 Javascript
js精确的加减乘除实例
2017/11/14 Javascript
vue2.0 路由不显示router-view的解决方法
2018/03/06 Javascript
微信小程序引入Vant组件库过程解析
2019/08/06 Javascript
React组件设计模式之组合组件应用实例分析
2020/04/29 Javascript
JS 5种遍历对象的方式
2020/06/16 Javascript
python爬虫入门教程之糗百图片爬虫代码分享
2014/09/02 Python
python中多个装饰器的调用顺序详解
2019/07/16 Python
Python二维码生成识别实例详解
2019/07/16 Python
Django中的静态文件管理过程解析
2019/08/01 Python
Django框架HttpResponse对象用法实例分析
2019/11/01 Python
Python经典五人分鱼实例讲解
2021/01/04 Python
欧洲领先的电子和电信零售商和服务提供商:Currys PC World Business
2017/12/05 全球购物
Doyoueven官网:澳大利亚健身服饰和配饰品牌
2019/03/24 全球购物
ABOUT YOU匈牙利:500个最受欢迎的时尚品牌
2019/07/19 全球购物
财务经理的岗位职责
2013/12/17 职场文书
书香校园建设方案
2014/05/02 职场文书
保卫钓鱼岛口号
2014/06/20 职场文书
商场租赁意向书
2014/07/30 职场文书
酒店圣诞节活动总结
2015/05/06 职场文书
大学生暑假实习总结
2015/07/13 职场文书
nginx刷新页面出现404解决方案(亲测有效)
2022/03/18 Servers
三种方式清除vue路由跳转router-link的历史记录
2022/04/10 Vue.js