Vue 实例中的生命周期钩子

时间:2022-09-06 19:51:42

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
实例。官方API

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 实例。官方API

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的整个生命周期中,它提供了一些生命周期钩子,给了我们执行自定义逻辑的机会。

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

完整的代码托管在 codepen

HTML结构:

{{ number }}

我们对 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。官方API

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

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

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

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

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

生命周期小结

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

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

官方示例中生命周期的运用

一个极简的Markdown编辑器

运行这个例子需要marked组件,通过以下方法引入:
在项目目录下运行 npm i marked -S, js 文件中 import marked from 'marked' 即可。
这个例子没有用到生命周期钩子,简单解读一下这段代码,

methods: {
update: _.debounce(function (e) {
this.input = e.target.value
}, 300)
}

html 中 textarea 绑定了 @input = "update" ,方法中用 debounce 指令设置了延时,在每次输
入后延时同步输入框的数据,减少了更新次数,提高性能。

GitHub 提交

这个例子从 Github 的 API 中获取了最新的 Vue.js 提交数据,并且以列表形式将它们展示了出
来。你可以轻松地切换 master 和 dev 分支。

created: function () {
this.fetchData()
},

在 created 钩子中用声明的 fetchData 函数获取ajax异步数据并渲染到页面。

内嵌组件

本例中,整合了第三方 jQuery 插件(select2),怎么做到的呢?就是把它内嵌在一个常用组件中

mounted: function () {
var vm = this
$(this.$el)
.val(this.value)
// init select2
.select2({ data: this.options })
// emit event on change.
.on('change', function () {
vm.$emit('input', this.value)
})
},

这个例子建立了组件 select2 ,在 mounted 钩子中增加了 jQuery 插件 select2 的方法,数据加载时
给元素增加这几个方法,获取 DOM 数据。

Vue 实例中的生命周期钩子的更多相关文章

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

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

  2. 了解angularjs中的生命周期钩子函数$onInit,$onChange,$onDestory,$postLink

     壹 ❀ 引 我在前面花了三篇文章用于介绍angularjs的指令directive,组件component,并专门花了一篇文章介绍directive与component的不同,其中提到在compon ...

  3. Vue.js系列:生命周期钩子

    开发人员提供了一个Web开发人员可以在Vue.js应用程序的整个生命周期中使用的各种方法的讨论. 生命周期钩子是在Vue对象生命周期的某个阶段执行的已定义方法.从初始化开始到它被破坏时,对象都会遵循不 ...

  4. Vue实例属性/方法/生命周期

    一 实例属性 var app = new Vue(); app.$el ===>返回当前挂在DOM对象. app.$data ===>返回当前实例data里面的数据 app.$option ...

  5. Vue 封装的组件生命周期钩子

    export default { // ... // 在组件初始化时调用,可以简单理解为页面加载时 created () { // 存在 localStorage 的缓存内容 if (localSto ...

  6. vue 生命周期钩子函数

    实例中的生命周期钩子可以分为以下8种情况: beforeCreate: 实例刚被创建,vue所有属性都还不存在 created: 实例创建完成,但$el还不存在 beforeMount:挂载之前 mo ...

  7. vue 生命周期钩子的理解 watch computed

    一  理解vue的生命周期,首先需要注意几个关键字 1. el :选择器 2. $el:对应选择器的template模板(html代码) 3. render:也是vue实例中的一项,其参数更接近vue ...

  8. vue生命周期图示中英文版Vue实例生命周期钩子

    vue生命周期图示中英文版Vue实例生命周期钩子知乎上近日有人发起了一个 “react 是不是比 vue 牛皮,为什么?” 的问题,Vue.js 作者尤雨溪12月4日正面回应了该问题.以下是尤雨溪回复 ...

  9. 浅析vue实例的生命周期(生命周期钩子)

    “每个 Vue 实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听.编译模板.将实例挂载到 DOM 并在数据变化时更新 DOM 等” ,在不同的生命周期内会经历不同的钩子函数(生命周期 ...

随机推荐

  1. AMD and CMD are dead之KMDjs内核之分号

    在老版本的kmdjs中,强制了分号的要求.但是总感觉不爽,因为在开发Ket - Kmdjs Extension Tools的时候,总需要导入一些开源的库,然后痛苦就来了,总是报错,一查,就是缺少分号! ...

  2. KEIL MDK STM32如何建立工程

    2. 3 4 5 6 7 QQ 463431476 8 9

  3. Android学习笔记(九)——布局和控件的自定义

    //此系列博文是<第一行Android代码>的学习笔记,如有错漏,欢迎指正! View是 Android中一种最基本的 UI组件,它可以在屏幕上绘制一块矩形区域,并能响应这块区域的各种事件 ...

  4. jsp中的四种对象作用域

    page:当前页面,也就是只要挑到别的页面就失效了,可以近似理解为java的this对象 request:一次会话,简单的理解就是一次请求范围内有效,例如如果通过forward方式跳转,则forwar ...

  5. margin的BUG

    在进行简单的div盒子嵌套时,发现设置margin-top时存在bug,然后就去谷歌搜索了一下,发现margin确实存在bug. bug的现象是父子元素嵌套时,如果子元素是块元素时,对块元素设置mar ...

  6. 应用emailAutoComplete&period;js来自动显示邮箱后缀列表

    我们经常有邮箱的人都特别清楚,在输入我们的邮箱时,会自动显示出邮箱后缀列表,这个用户体验是不错的. 操作据悉——当我们输入文字时,会自动有个邮箱后缀名的列表.      而我这边的代码是,应用jque ...

  7. 第三十二篇、iOS 10开发

    1.语音识别 苹果官方在文档中新增了API   Speech,那么在以前我们处理语音识别非常的繁琐甚至很多时候可能需要借助于第三方框架处理,那么苹果推出了这个后,我们以后处理起来就非常的方便了,spe ...

  8. 读取本地outlook邮件内容

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. Spring boot &plus; mybatis &plus; orcale实战(干货)

    废话少说,直接上步骤: 第一步:安装好IDEA(此处省略) 第二步:在IDEA新建springboot工程 第三步:在springboot工程的pom.xml添加oracle和mybait依赖 &lt ...

  10. Expressions versus statements in JavaScript

    Statements and expressions An expression produces a value and can be written wherever a value is exp ...