对vue生命周期的深入理解


Posted in Vue.js onDecember 03, 2020

一.Vue生命周期简介

官网:https://cn.vuejs.org/v2/api/#beforeCreate

Vue实例从创建到销毁的过程,就是生命周期。详细来说也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程。

首先我们来看一下官网的生命周期图(我自己做了一点点注释):

对vue生命周期的深入理解 

Vue提供给我们的钩子为上图的红色的文字

二.钩子详解

 1.beforeCreate

在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <!-- 引入vue.js -->
 <script type="text/javascript" src='./vue.js'></script>
</head>
<body>
 <div id="app">
 <input type="text" name="" v-model="message">
 {{message}} 
 </div>
 <script type="text/javascript">
 //实例化Vue
 var app = new Vue({
  el:'#app',
  data:{
  message:'this is mseeage'
  },
  //时刻监测数据message的变化,一但那变化就会吊该函数
  watch:{
  //message必须和监测的data名字一样
  message:function(){
   console.log('watch:','message 变了')
  }
  },
  methods:{
  init:function(){
   console.log('这是初始化方法')
  }
  },
  //我们在beforeCreate钩子中调用Vue的data和method
  beforeCreate:function(){
  console.log("beforeCreate",this.message);
  this.init();
  }
 })
 </script> 
</body>
</html>

我们在上面的例子中在的beforeCreate钩子中调用Vue的data和method,来看一下结果

对vue生命周期的深入理解 

可以看到Vue中的data和方法都是去不到的,并且是在wath之前执行

2.created

实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。

主要应用:调用数据,调用方法,调用异步函数

<div id="app">
 <ul>
  <li v-for="(item,index) of list" key="index">{{item}}--{{message}}</li>
 </ul>

 <p>p1</p>
 <p>p1</p>
 <p>p1</p>
</div>
<script type="text/javascript">
 //实例化Vue
 var app = new Vue({
  el:'#app',
  data:{
   message:'this is mseeage',
   list:['aaaaaaaa','bbbbbbb','ccccccc']
  },
  //时刻监测数据message的变化,一但那变化就会吊该函数
  watch:{
   //message必须和监测的data名字一样
   message:function(){
    console.log('watch:','message 变了')
   }
  },
  methods:{
   foo:function(){
    console.log('foo : ','这是初始化方法')
   }
  },
  //created钩子
  created:function(){
   //调用Vue的data
   console.log("created : ",this.message);
   //调用Vue方法
   this.foo();
   //因为我们是通过v-for循环遍历li,所以created之前挂载阶段还没开始.是无法获取li的个数的
   console.log('li数量:',document.getElementsByTagName('li').length);
   //直接加载出来的DOM是可以直接获取到的
   console.log('p个数:',document.getElementsByTagName('p').length);
  },
 })
</script>

结果

对vue生命周期的深入理解 

可以看到:created钩子可以获取Vue的data,调用Vue方法,获取原本HTML上的直接加载出来的DOM,但是无法获取到通过挂载模板生成的DOM(例如:v-for循环遍历Vue.list生成li)

3.beforeMount

在挂载开始之前被调用:相关的 render 函数(模板)首次被调用。

例如通过v-for生成的html还没有被挂载到页面上

(接 2created的代码)

beforeMount: function () {
  console.log('beforeMount:',document.getElementsByTagName('li').length);
 },

结果 beforeMount: 1

4.mounted

el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。

有初始值的DOM渲染,例如我们的初始数据list,渲染出来的li,只有这里才能获取

(接 2created的代码)

mounted: function () {
 console.log('mounted:',document.getElementsByTagName('li').length);
},

结果 mounted: 3

可以看到到这里为止,挂载到实例上了,我们可以获取到li的个数了

5.beforeUpdate

数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。

当我们更改Vue的任何数据,都会触发该函数

beforeUpdate: function () {
  console.log('beforeUpdate 钩子执行...');
  console.log('beforeUpdate:'+this.message)
 },

6.updated

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。

该钩子在服务器端渲染期间不被调用。

数据更新就会触发(vue所有的数据只有有更新就会触发),如果想数据一遍就做统一的处理,可以用这个,如果想对不同数据的更新做不同的处理可以用nextTick,或者是watch进行监听

updated: function () {
  console.log('updated 钩子执行...');
  console.log('updated:',this.message)
},

7.beforeDestroy

实例销毁之前调用。在这一步,实例仍然完全可用。

8.destroyed

Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。

<div id="app">
</div>
<script type="text/javascript">
 //实例化Vue
 var app = new Vue({
  el:'#app',
  data:{
   message:'this is mseeage',
  },
  beforeDestroy: function () {
   console.log('beforeDestroy 钩子执行...',this.message)
  },
  destroyed: function () {
   console.log('destroyed 钩子执行...',this.message)
  }
 })
 //销毁Vue实例,触发beforeDestroy和destroyed函数
 app.$destroy()
</script>

结果:

对vue生命周期的深入理解 

可以看打到销毁Vue实例时会调用这两个函数

补充$mount

当你vue没有挂在el时,我们可以用$mount

var app = new Vue({
 data:{
   message:'this is mseeage',
  },
}).$mount('#app')

三.钩子的一些实战用法

1.异步函数

这里我们用定时器来做异步函数

<div id="app">
 <ul>
  <li v-for="(item,index) of list" key="index">{{item}}</li>
 </ul>
</div>

<script type="text/javascript">
 var app = new Vue({
  el:'#app',
  data:{
   list:['aaaaaaaa','bbbbbbb','ccccccc']
  },
  created:function(){
   consoloe.log('created异步:aaaaa');
   //异步获取数据
   // 因为是异步,就和我们ajax获取数据一样
   setTimeout(()=>{
    this.list=['111','222','333','444'],
    console.log('created异步:',document.getElementsByTagName('li').length);
   },0)
  },
  mounted: function () {
   console.log('mounted:',document.getElementsByTagName('li').length);
  },
  updated: function () {
   console.log('updated:',document.getElementsByTagName('li').length)
  },
 })
</script>

结果为:

create: aaaaaaaa
mounted: 3
created异步函数: 3
updated: 4

解释:

可以看到因为是在created的钩子中加入异步函数,所以函数的执行顺序为:

ceated钩子,mounted钩子,异步函数,updated钩子(根据事件队列原理,只有在updated后,li才是真的DOM渲染为4个,所以异步函数中获取的li的个数时是没有变化的li的个数)。

因为mounted获取到的是我们在Vue的data中设置初始值渲染的DOM,而我们是在异步函数中变化的list数据,所以mounted获取的li的个数为3。

update函数是只要数据vue绑定的数据变化就会触发,所以最后执行,为4

这是不是意味着可以直接在update函数中操作呢,其实不是,因为update函数是针对vue的所有数据的变化,而我们也有可能会有其他数据的变化。

例如下面的例子:

//我们利用异步函数改变了两次list,会发现update被触发了2次
created:function(){
  //异步获取数据
  // 因为是异步,就和我们ajax获取数据一样
  setTimeout(()=>{
    this.list=['111','222','333','444'],
    console.log('created异步:',document.getElementsByTagName('li').length);
  },0)
  setTimeout(()=>{
    this.list=['快乐大本营','脚踏实地','300033','天天向上','好好学习'],
    console.log('created异步:',document.getElementsByTagName('li').length);
  },1000)
},
mounted: function () {
  console.log('mounted:',document.getElementsByTagName('li').length);
},
updated: function () {
  console.log('updated:',document.getElementsByTagName('li').length)
},

结果为:

对vue生命周期的深入理解

2.Vue.nextTick对异步函数的结果进行操作

我们想要改变数据时,各自触发各自的方法

created:function(){
//异步获取数据
// 因为是异步,就和我们ajax获取数据一样

 //为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
 setTimeout(()=>{
  this.list=['111','222','333','444'],
  console.log('created异步:',document.getElementsByTagName('li').length);
  this.$nextTick(function(){
   console.log("created$nextTick:",document.getElementsByTagName('li').length)
  });
 },0)
 setTimeout(()=>{
  this.list=['快乐大本营','脚踏实地','300033','天天向上','好好学习'],
  console.log('created异步:',document.getElementsByTagName('li').length);
  this.$nextTick(function(){
   console.log("created$nextTick:",document.getElementsByTagName('li').length)
  });
 },1000)
},
mounted: function () {
 console.log('mounted:',document.getElementsByTagName('li').length);
},
updated: function () {
 console.log('updated:',document.getElementsByTagName('li').length)
},

结果:

对vue生命周期的深入理解 

我们可以看到通过$nextTick我们可以对异步函数的结果进行各自的操作

到此这篇关于对vue生命周期深入理解的文章就介绍到这了,更多相关vue生命周期的理解内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Vue.js 相关文章推荐
使用vue编写h5公众号跳转小程序的实现代码
Nov 27 Vue.js
vue 实现基础组件的自动化全局注册
Dec 25 Vue.js
浅析vue中的nextTick
Dec 28 Vue.js
vue-cli4.0多环境配置变量与模式详解
Dec 30 Vue.js
Vue中的nextTick作用和几个简单的使用场景
Jan 25 Vue.js
如何封装Vue Element的table表格组件
Feb 06 Vue.js
Vue通过懒加载提升页面响应速度
May 10 Vue.js
详解Vue的列表渲染
Nov 20 Vue.js
Vue3如何理解ref toRef和toRefs的区别
Feb 18 Vue.js
VUE中的v-if与v-show区别介绍
Mar 13 Vue.js
vue生命周期钩子函数以及触发时机
Apr 26 Vue.js
Vue 打包后相对路径的引用问题
Jun 05 Vue.js
用vue设计一个日历表
Dec 03 #Vue.js
实用的 vue tags 创建缓存导航的过程实现
Dec 03 #Vue.js
如何实现vue的tree组件
Dec 03 #Vue.js
Vue实现图书管理小案例
Dec 03 #Vue.js
Vue router安装及使用方法解析
Dec 02 #Vue.js
vue3.0中setup使用(两种用法)
Dec 02 #Vue.js
vue3.0+vue-router+element-plus初实践
Dec 02 #Vue.js
You might like
php preg_filter执行一个正则表达式搜索和替换
2012/02/27 PHP
PHP 透明水印生成代码
2012/08/27 PHP
Codeigniter框架实现获取分页数据和总条数的方法
2014/12/05 PHP
php二维码生成以及下载实现
2017/09/28 PHP
JQUERY获取form表单值的代码
2010/07/17 Javascript
仅IE9/10同时支持script元素的onload和onreadystatechange事件分析
2011/04/27 Javascript
js实现拖拽 闭包函数详细介绍
2012/11/25 Javascript
原生js实现跨浏览器获取鼠标按键的值
2013/04/08 Javascript
js showModalDialog弹出窗口实例详解
2014/01/07 Javascript
跟我学习javascript的Date对象
2015/11/19 Javascript
阻止表单提交按钮多次提交的完美解决方法
2016/05/16 Javascript
Bootstrap学习系列之使用 Bootstrap Typeahead 组件实现百度下拉效果
2016/07/07 Javascript
JS实现放大、缩小及拖拽图片的方法【可兼容IE、火狐】
2016/08/23 Javascript
Dropzone.js实现文件拖拽上传功能(附源码下载)
2016/11/22 Javascript
jQuery Validate插件自定义验证规则的方法
2016/12/27 Javascript
vue+ElementUI实现订单页动态添加产品数据效果实例代码
2017/07/13 Javascript
解决vue处理axios post请求传参的问题
2018/03/05 Javascript
react-native 实现购物车滑动删除效果的示例代码
2021/01/15 Javascript
在漏洞利用Python代码真的很爽
2007/08/26 Python
Python的Bottle框架的一些使用技巧介绍
2015/04/08 Python
解决python3 json数据包含中文的读写问题
2018/05/10 Python
Python 多线程不加锁分块读取文件的方法
2018/12/11 Python
python 图像平移和旋转的实例
2019/01/10 Python
基于Python实现用户管理系统
2019/02/26 Python
python使用Plotly绘图工具绘制气泡图
2019/04/01 Python
Python GUI编程 文本弹窗的实例
2019/06/11 Python
基于SQLAlchemy实现操作MySQL并执行原生sql语句
2020/06/10 Python
使用python对excel表格处理的一些小功能
2021/01/25 Python
css3 column实现卡片瀑布流布局的示例代码
2018/06/22 HTML / CSS
html5 Canvas画图教程(10)—把面拆成线条模拟出圆角矩形
2013/01/09 HTML / CSS
HTML5 window/iframe跨域传递消息 API介绍
2013/08/26 HTML / CSS
意大利香水和化妆品购物网站:Parfimo.it
2019/10/06 全球购物
服务承诺书范文
2014/05/19 职场文书
2015年基层党建工作总结
2015/05/14 职场文书
上学路上观后感
2015/06/16 职场文书
幼儿园教师教育随笔
2015/08/14 职场文书