VUE

Vue 生命周期全解

2019-08-24  本文已影响0人  Wermdany

一般说的 Vue 生命周期指的是打包完成后的 js 代码去执行的过程,区别于开发环境和 HTML 嵌入 Vue.js。

注意:本文中,“本实例”、“本组件”、“本页面”等称呼,都是一个意思。

生命周期函数的局限性

  1. 不可阻止(无法阻止周期的运行,除非发生错误)。
  2. 全局性(函数都是全局,在更新系类周期函数中,对具体变化操作变得很难)
  3. 目前想不到了,或无法用语言表达出来。

beforeCreate( 创建前 )

也就是执行new Vue(),读取了代码的信息,但是 Vue 的一系列操作还未执行,参考 JS 的New操作符,也就初始化了 Vue ,也就包括了生命周期,然后执行这个函数。

在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el 和 data 并未初始化,因此无法访问 methods, data, computed ……等属性上的方法和数据。

可以干啥:

因为生命周期的不可阻止特性,也就意味当前页面必然加载了,在使用了 Vuex 的时候,可以在这个阶段去把本实例需要的东西进行同步获取或者创建准备。

但是不要去进行异步操作(常见:数据请求),这时候没有 data,无法放进 data,多此一举,就算是你保存到 vuex 或本地缓存,在 created 阶段也不一定能获取,因为获取数据一般都是异步请求,使用async/await可以解决。

同步操作是没有任何问题的,在这个阶段可以进行同步操作,比如进行数据准备,在 created 把准备的数据赋值过来 。

不论是异步操作还是同步操作,由于不是通过 Vue 响应式的获取,无法触发 Vue 的一些初始动画效果和监听效果等,需要慎重考虑。

created ( 创建后 )

这个阶段有什么?

  1. 当前实例的方法(methods)
  2. 监听器(watch)
  3. 属性(data)
  4. watch/event 事件回调(注意是回调,并不是操作)
  5. 数据观测(已经可以使用 vue 的响应特性了,最直观的表现就是获取数据可以触发初始动画)
  6. 计算属性(computed)等等操作。
  7. 其他不常用的实例的属性/方法

以上这些都存在后,再执行这个函数,也就是说你可以对以上进行操作和调用。

$el 属性目前不可见,至于 dom 等更不可能。

通常我们可以在这里对实例进行预处理。

一些争议:

在本阶段进行异步数据请求。

可以这样,但是不建议,有些关键数据没获取或发生错误,页面布局会崩溃掉,并且由于开文的不可阻挡特性,页面无法阻断。
建议使用 Vue-Router,这时当前实例还拥有组件内的 beforeRouteEnter 钩子,其实就是组建内导航守卫,可以阻止跳转。

beforeMount

挂载开始之前被调用。

其实 Vue 的打包就是把 页面结构->html 都是经过处理,生成 rander 函数,页面渲染的时候再通过解析函数,解析成 html。

编译模板为虚拟 dom 放入到 render 函数中准备渲染

虚拟 DOM 和编译模板,不是一个操作,除非你对 Vue 机制特别了解,现在你可以把它看成一个东西。

这时,如果你获取 dom 会发现结果为类似于<b>{{name}}<b>的差值表达式,获取的是模板中的 DOM, data 还没有进行赋值,只是有了虚拟 DOM。

虚拟 DOM 你就可以看成 Rander 函数,但是要比 rander 函数复杂得多。

在这些完成后执行这个函数。

也就是说 data 属性,这时候你还可以进行赋值和操作。

注意此时还没有挂在 html 到页面上。

mounted

开始执行 Rander,建议了解: 渲染函数

生成了真实的 HTML ,可以进行 DOM 操作和实例操作 。

这时才会触发这个函数

mounted 只会执行一次。

beforeUpdata (更新前)

数据发生了变化

执行这个函数

发生在虚拟 DOM 重新渲染和打补丁之前,可以在该钩子中进一步地更改状态。

这时候你对数据进行修改,会影响创建的新的虚拟 DOM

创建的虚拟 DOM 会对内存保存的虚拟 DOM 进行 diff 运算。

所以在这个阶段修改数据,会对本次触发更新的变化造成干扰,除非你合理的在本函数内进行数据修改,应为本函数是一个全局的函数,没有任何的回调和传参,一般不做什么事,最多也就事做个日志系统。

找到具体变化的 DOM,去对这些变化的 DOM 进行渲染。

把新的虚拟 DOM 替换掉旧的虚拟 DOM,等待下次 diff.

注意:现在 Vue 已经不是每次都要对本实例进行完全的虚拟 DOM 进行渲染,会根据虚拟 DOM 的 ID 值,快速找到,所以本阶段,真的没啥需要干的事,或许我水平不到。

updated (更新后)

更新后的 DOM 页面,类似于页面初次渲染完成。

可以对更新后的页面进行 DOM 操作和实例操作。

但是这还是一个全局函数,任何的数据变化都会执行,性能问题很大。

局部更新:要想获取更新后的 DOM 建议在数据改变操作后使用 $nextTick来获取对数据更新后的操作。

至于全局更新:对更新后 DOM 进行操作,还是要在这个函数内操作,虽然有性能问题,而且你几乎无法判断触发本次操作到底是那个数据变化造成的。

不要在这个阶段进行数据更改,会触发死循环。

beforeDestrioy (销毁前)

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

先执行这个函数

这时一切正常,任何操作都可以,做一些清除操作,比如缓存,比如离开的回调。

执行你对组件销毁前的操作

执行 Vue 自动的销毁方法,销毁清除计时器、清除非指令绑定的事件。

一般情况下,Vue 会自动的销毁当前实例的事件和监听等等,但是在使用 EventBus 的时候必须要手动清除。因为不是当前实例创建的,属于手动创建,Vue 处理的只是 DOM 和数据,至于事件的绑定在 JS 事件栈中保存,如果不手动销毁,再次创建本组件的时候,会触发两次(现在一般事件都是 DOM3 的事件,一个元素能够绑定多个相同事件)。

一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的 dom 事件

destroyed(销毁后)

在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用

什么都没了,也没啥操作得了,也可以做点善后操作,虽然当前实例啥都没了,但是这个函数还是在当前实例的生命周期内,也就属于亲人,当然还是可以操作的。

其他

想到了再补充吧

防喷

由于水平有限,和时间仓促,有问题恳请指出。

参考连接

Vue - 生命周期详解

上一篇下一篇

猜你喜欢

热点阅读