对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 +WebSocket + WaveSurferJS 实现H5聊天对话交互的实例
Nov 18 Vue.js
详解vue 组件注册
Nov 20 Vue.js
实用的 vue tags 创建缓存导航的过程实现
Dec 03 Vue.js
Vue实现小购物车功能
Dec 21 Vue.js
vue+openlayers绘制省市边界线
Dec 24 Vue.js
vue 使用class创建和清除水印的示例代码
Dec 25 Vue.js
Vue看了就会的8个小技巧
Jan 21 Vue.js
vue首次渲染全过程
Apr 21 Vue.js
关于Vue Router的10条高级技巧总结
May 06 Vue.js
Vue如何实现组件间通信
May 15 Vue.js
vue实现水波涟漪效果的点击反馈指令
May 31 Vue.js
vite+vue3.0+ts+element-plus快速搭建项目的实现
Jun 24 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正则表达式 /i, /is, /s, /isU等介绍
2014/10/23 PHP
在Nginx上部署ThinkPHP项目教程
2015/02/02 PHP
浅谈PHP链表数据结构(单链表)
2016/06/08 PHP
PHP Cli 模式设置进程名称的方法
2019/06/12 PHP
JavaScript高级程序设计
2006/12/29 Javascript
Javascript Object.extend
2010/05/18 Javascript
Js实现自定义右键行为
2015/03/26 Javascript
jQuery+CSS实现的网页二级下滑菜单效果
2015/08/25 Javascript
学习javascript面向对象 理解javascript原型和原型链
2016/01/04 Javascript
举例讲解jQuery中可见性过滤选择器的使用
2016/04/18 Javascript
对js中回调函数的一些看法
2016/08/29 Javascript
微信小程序 实战小程序实例
2016/10/08 Javascript
详解用webpack2.0构建vue2.0超详细精简版
2017/04/05 Javascript
使用JavaScript根据图片获取条形码的方法
2017/07/04 Javascript
微信小程序联网请求的轮播图
2017/07/07 Javascript
浅谈vuex之mutation和action的基本使用
2017/08/29 Javascript
vue里面v-bind和Props 利用props绑定动态数据的方法
2018/08/27 Javascript
微信小程序云开发 生成带参小程序码流程
2019/05/18 Javascript
Vue中跨域及打包部署到nginx跨域设置方法
2019/08/26 Javascript
[00:42]《辉夜杯》—职业组预选赛12月3日15点 正式打响
2015/12/03 DOTA
python实现播放音频和录音功能示例代码
2018/12/30 Python
简单了解Pandas缺失值处理方法
2019/11/16 Python
python获取array中指定元素的示例
2019/11/26 Python
浅谈HTML5 服务器推送事件(Server-sent Events)
2017/08/01 HTML / CSS
医学院毕业生自荐信
2013/11/08 职场文书
优秀士兵个人事迹材料
2014/01/19 职场文书
教师研修随笔感言
2014/01/23 职场文书
销售员求职个人的自我评价
2014/02/19 职场文书
《少年王冕》教学反思
2014/04/11 职场文书
机电一体化专业求职信
2014/07/22 职场文书
学习实践科学发展观心得体会
2014/09/10 职场文书
英语邀请函范文
2015/02/02 职场文书
Nginx图片服务器配置之后图片访问404的问题解决
2022/03/21 Servers
Python接口自动化之文件上传/下载接口详解
2022/04/05 Python
Win11 引入 Windows 365 云操作系统,适应疫情期间混合办公模式:启动时直接登录、模
2022/04/06 数码科技
不负正版帝国之名 《重返帝国》引领SLG手游制作新的标杆
2022/04/07 其他游戏