详解Vue 实例中的生命周期钩子


Posted in Javascript onMarch 21, 2017

Vue 框架的入口就是 Vue 实例,其实就是框架中的 view model ,它包含页面中的业务处理逻辑、数据模型等,它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。

Vue 实例

在文档中经常会使用 vm 这个变量名表示 Vue 实例,在实例化 Vue 时,需要传入一个选项对象,它可以包含数据(data)、模板(template)、挂载元素(el)、方法(methods)、生命周期钩子(lifecyclehook)等选项。

Vue 实例化的选项

需要注意的是含 this 的函数大多不要使用箭头函数,因为我们期望 this 指向 Vue 实例。

data

Vue 实例的数据都保存在 data 对象中,Vue 将会递归将 data 的属性转换为 getter/setter,从而让 data 的属性能够响应数据变化。

var data = { a: 1 }
// 直接创建一个实例
var vm = new Vue({
 data: data
})
vm.a // -> 1
vm.$data === data // -> true

这样数据就绑定在 HTML 中,Vue 框架监视 data 的数据变化,自动更新 HTML 内容。

computed

计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue

实例。

var vm = new Vue({
 data: { a: 1 },
 computed: {
 // 仅读取,值只须为函数
 aDouble: function () {
  return this.a * 2
 },
 // 读取和设置
 aPlus: {
  get: function () {
  return this.a + 1
  },
  set: function (v) {
  this.a = v - 1
  }
 }
 }
})
vm.aPlus // -> 2
vm.aPlus = 3
vm.a  // -> 2
vm.aDouble // -> 4

这里可以省略setter,如果省略了setter,那么值就可以是普通函数,但是必须有返回值。

methods

methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this 自动绑定为 Vue 实例。

var vm = new Vue({
 data: { a: 1 },
 methods: {
 plus: function () {
  this.a++
 }
 }
})
vm.plus()
vm.a // 2

看下面这个例子,methods 和 computed 看起来可以做同样的事情,单纯看结果两种方式确实是相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。相比而言,只要发生重新渲染,method 调用总会执行该函数。

var vm = new Vue({
 el: '#example',
 data: {
 message: 'Hello'
 },
 computed: {
 // a computed getter
 reversedMessage: function () {
  // `this` points to the vm instance
  return this.message.split('').reverse().join('')
 }
 }
})

watch

一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。

var vm = new Vue({
 data: {
 a: 1,
 b: 2,
 c: 3
 },
 watch: {
 // 监控a变量变化的时候,自动执行此函数
 a: function (val, oldVal) {
  console.log('new: %s, old: %s', val, oldVal)
 },
 // 深度 watcher
 c: {
  handler: function (val, oldVal) { /* ... */ },
  deep: true
 }
 }
})
vm.a = 2 // -> new: 2, old: 1

Vue 实例的生命周期

Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。通俗说就是 Vue 实例从创建到销毁的过程,就是生命周期。

在Vue的整个生命周期中,它提供了一些生命周期钩子,给了我们执行自定义逻辑的机会。

接下来我们用几个例子来看看生命周期钩子是怎么用的:

HTML结构:

<div id="app">
 <p>{{ number }}</p>
 <input type="text" name="btnSetNumber" v-model="number">
</div>

我们对 input 和 p 绑定了data 对象的 number 数据,Vue 实例构建如下:

var app = new Vue({   
 el: '#app',    
 data: {     
  number: 1
 }
})

在实例中分别在每个生命周期钩子中 console.log('钩子名称',this.number) 我们发现,第一次页面加载时触发了 beforeCreate, created, beforeMount, mounted 这几个钩子,data 数据在 created 中可获取到。

再去 console.log('mounted: ', document.getElementsByTagName('p')[0]) ,DOM 渲染在 mounted 中已经
完成。

我们再试着去更改 input 输入框中的内容,可以看到输入框上方的数据同步发生改变,这就是数据绑定的效果,在更新数据时触发 beforeUpdate 和 updated 钩子,且在 beforeUpdate 触发时,数据已更新完毕。

而 destroy 仅在调用app.$destroy();时触发,对 vue 实例进行销毁。销毁完成后,我们再重新改变 number 的值,vue 不再对此动作进行响应了。但是原先生成的dom元素还存在,可以这么理解,执行了destroy操作,后续就不再受vue控制了。

Vue.nextTick

在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

Vue.nextTick(function () {
 // DOM 更新了
})

官方还提供了一种写法,vm.$nextTick,用 this 自动绑定到调用它的实例上

created() {
 setTimeout(() => {
   this.number = 100
   this.$nextTick(() => {
   console.log('nextTick', document.getElementsByTagName('p')[0])
   })
 },100)
}

什么时候需要用的Vue.nextTick()

在 Vue 生命周期的 created() 钩子函数进行的 DOM 操作一定要放在 Vue.nextTick() 的回调函数中。原因是什么呢,原因是在 created() 钩子函数执行的时候 DOM 其实并未进行任何渲染,而此时进行 DOM 操作无异于徒劳,所以此处一定要将 DOM 操作的 js 代码放进 Vue.nextTick() 的回调函数中。与之对应的就是 mounted 钩子函数,因为该钩子函数执行时所有的 DOM 挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。

在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的 DOM 结构的时候,这个操作都应该放进 Vue.nextTick() 的回调函数中。

生命周期小结

生命周期钩子的一些使用方法:

  1. beforecreate : 可以在这加个loading事件,在加载实例时触发
  2. created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
  3. mounted : 挂载元素,获取到DOM节点
  4. updated : 如果对数据统一处理,在这里写上相应函数
  5. beforeDestroy : 可以做一个确认停止事件的确认框
  6. nextTick : 更新数据后立即操作dom

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

Javascript 相关文章推荐
JQuery 选项卡效果(JS与HTML的分离)
Apr 01 Javascript
JavaScript和JQuery实用代码片段(一)
Apr 07 Javascript
javascript两种function的定义介绍及区别说明
May 02 Javascript
JQuery中$(document)是什么意思有什么作用
Jul 21 Javascript
原生javascript实现图片按钮切换
Jan 12 Javascript
原生js制作简单的数字键盘
Apr 24 Javascript
浅谈jquery.form.js的ajaxSubmit和ajaxForm的使用
Sep 09 Javascript
详解Sea.js中Module.exports和exports的区别
Feb 12 Javascript
微信小程序实战之登录页面制作(5)
Mar 30 Javascript
详解基于Koa2开发微信二维码扫码支付相关流程
May 16 Javascript
使用jquery DataTable和ajax向页面显示数据列表的方法
Aug 09 jQuery
一篇文章带你从零快速上手Rollup
Sep 07 Javascript
十大热门的JavaScript框架和库
Mar 21 #Javascript
Bootstrap 设置datetimepicker在屏幕上面弹出设置方法
Mar 21 #Javascript
js中编码函数:escape,encodeURI与encodeURIComponent详解
Mar 21 #Javascript
Omi v1.0.2发布正式支持传递javascript表达式
Mar 21 #Javascript
jQuery插件HighCharts绘制简单2D柱状图效果示例【附demo源码】
Mar 21 #jQuery
jQuery插件HighCharts绘制简单2D折线图效果示例【附demo源码】
Mar 21 #jQuery
jQuery插件HighCharts绘制2D饼图效果示例【附demo源码下载】
Mar 21 #jQuery
You might like
PHP syntax error, unexpected $end 错误的一种原因及解决
2008/10/25 PHP
Laravel利用gulp如何构建前端资源详解
2018/06/03 PHP
PHP语言对接抖音快手小红书视频/图片去水印API接口源码
2020/08/11 PHP
Jquery 弹出层插件实现代码
2009/10/24 Javascript
js 蒙版进度条(结合图片)
2010/03/10 Javascript
jQueryUI写一个调整分类的拖放效果实现代码
2012/05/10 Javascript
JS getAttribute和setAttribute(取得和设置属性)的使用介绍
2013/07/10 Javascript
简单谈谈Javascript中类型的判断
2015/10/19 Javascript
js行号显示的文本框实现效果(兼容多种浏览器 )
2015/10/23 Javascript
AngularJS教程之环境设置
2016/08/16 Javascript
Vue数据驱动模拟实现4
2017/01/12 Javascript
ES6新特性之变量和字符串用法示例
2017/04/01 Javascript
.net MVC+Bootstrap下使用localResizeIMG上传图片
2017/04/21 Javascript
vue2.0+vue-dplayer实现hls播放的示例
2018/03/02 Javascript
vue拦截器实现统一token,并兼容IE9验证功能
2018/04/26 Javascript
基于vue-element组件实现音乐播放器功能
2018/05/06 Javascript
vue 地图可视化 maptalks 篇实例代码详解
2019/05/21 Javascript
详解如何在Javascript中使用Object.freeze()
2020/10/18 Javascript
[02:06]DOTA2肉山黑名单魔法终结者 敌法师中文配音鉴赏
2013/06/17 DOTA
[01:01:29]2018DOTA2亚洲邀请赛 4.4 淘汰赛 VP vs Liquid 第一场
2018/04/05 DOTA
使用Turtle画正螺旋线的方法
2017/09/22 Python
python实现趣味图片字符化
2019/04/30 Python
Python增强赋值和共享引用注意事项小结
2019/05/28 Python
50行Python代码实现视频中物体颜色识别和跟踪(必须以红色为例)
2019/11/20 Python
pytorch:实现简单的GAN示例(MNIST数据集)
2020/01/10 Python
使用Python求解带约束的最优化问题详解
2020/02/11 Python
python爬虫筛选工作实例讲解
2020/11/23 Python
世界著名的顶级牛排:Omaha Steak(奥马哈牛排)
2016/09/20 全球购物
亚洲航空公司官方网站:AirAsia
2019/11/25 全球购物
J2EE中的容器都包括哪些
2013/08/21 面试题
教师应聘个人求职信
2013/12/10 职场文书
50岁生日感言
2014/01/23 职场文书
电脑销售顾问自荐信
2014/01/29 职场文书
自查自纠工作总结
2014/10/15 职场文书
检讨书范文
2019/04/16 职场文书
Python使用socket去实现TCP客户端和TCP服务端
2022/04/12 Python