【Vue】详解Vue生命周期

目录

 

正文

回到顶部

 

 

 

回到顶部

Vue 实例的生命周期全过程(图)

 

(这里的红边圆角矩形内的都是对应的 Vue 实例的钩子函数)
回到顶部

在 beforeCreate 和 created 钩子函数间的生命周期

 

在 beforeCreate 和 created 之间,进行数据观测 (data observer) ,也就是在这个时候开始监控 data 中的数据变化了,同时初始化事件
 
 
回到顶部

created 钩子函数和 beforeMount 间的生命周期

 

对于 created 钩子函数和 beforeMount 间可能会让人感到有些迷惑,下面我就来解释一下:

el 选项的有无对生命周期过程的影响

首先系统会判断对象中有没有 el 选项
有 el 选项,则继续编译过程
没有 el 选项,则停止编译,也意味着暂时停止了生命周期,直到 vm.$mount(el)
下面我展示一下:
new Vue({
  el: '#app',
  beforeCreate: function () {
    console.log('调用了 beforeCreat 钩子函数') },
  created: function () {
    console.log('调用了 created 钩子函数') },
  beforeMount: function () {
    console.log('调用了 beforeMount 钩子函数') },
  mounted: function () {
    console.log('调用了 mounted 钩子函数') }
})

 

demo 如下:

 

可以看到,在 el 选项填写且正确的时候,生命周期将正常进行
 
而当我们把 el 去掉:
new Vue({
  beforeCreate: function () {
    console.log('调用了 beforeCreat 钩子函数') },
  created: function () {
    console.log('调用了 created 钩子函数') },
  beforeMount: function () {
    console.log('调用了 beforeMount 钩子函数') },
  mounted: function () {
    console.log('调用了 mounted 钩子函数') }
})

 

demo:
 

 

可以看到,生命周期的钩子函数执行到 created 就结束了
而当我们不加 el 选项,但是手动执行 vm.$mount(el) 方法的话,也能够使暂停的生命周期进行下去,例如:
var vm = new Vue({
  beforeCreate: function () {
    console.log('调用了 beforeCreat 钩子函数') },
  created: function () {
    console.log('调用了 created 钩子函数') },
  beforeMount: function () {
    console.log('调用了 beforeMount 钩子函数') },
  mounted: function () {
    console.log('调用了 mounted 钩子函数') }
})
vm.$mount('#app')

 

demo 如下,可以看到,这个时候虽然对象中没有 el 参数,但通过 $mount(el) 动态添加的方式,也能够使生命周期顺利进行
 

 

template 参数选项的有无对生命周期的影响

 

 

1.如果 Vue 实例对象中有 template 参数选项,则将其作为模板编译成 render 函数
2.如果没有 template 参数选项,则将外部的 HTML 作为模板编译(template),也就是说,template 参数选项的优先级要比外部的 HTML 高
3.如果 1,2 条件都不具备,则报错
 
我们可以把模板写在 template 参数选项中:
new Vue({
  el: '#app',
  template: '<div id="app"><p> 模板在 templated 参数中找到了哟 ~</p></div>'
})
demo:

 

 

 

也可以把参数选项写在外部 HTML 中,像这样:
 
外部 HTML:
<div id="app"><p> 模板是在外部 HTML 中找到的 ~</p></div>
创建对象实例:
new Vue({
  el: '#app'
})

 

demo:

 

那么有趣的问题来了,当模板同时放在 template 参数选项和外部 HTML 中,会怎样呢?
例如:
外部 HTML:
<div id="app"><p> 模板是在外部 HTML 中找到的 ~</p></div>

 

 
创建 Vue 实例(包含 template 参数选项)
new Vue({
  el: '#app',
  template: '<div id="app"><p> 模板在 templated 参数中找到了哟 ~</p></div>'
})

 

demo 如下:

 

很显然,正如我上面下的结论一样,最终显示的是“模板在 templated 参数中找到了哟 ~”而不是“模板是在外部 HTML 中找到的 ~”,因为 template 参数的优先级比外部 HTML 的优先级要高
 
【注意】
1. 为什么判断 el 要发生在判断 template 前面呢
 
因为 Vue 需要通过 el 的“选择器”找到对应的 template。总结一下上述的过程,Vue 通过 el 参数去找到对应的 template。然后, 根据 el 参数给出的“选择器”,首先去 Vue 实例对象本身的 template 选项参数中找,如果没有 template 参数,则到外部 HTML 中寻找,找到后将模板编译成 render 函数
 
2. 实际上,在 Vue 中,有 render 函数这个选项, 它以 createElement 作为参数,做渲染操作。当然你也可以不调用 createElement,而直接嵌入 JSX(学习 react 的同学对此应该很熟悉吧)。
new Vue({
  el: '#demo',
  render (createElement) {
    return (....)
  }
})

 

【注意】render 选项参数比 template 更接近 Vue 解析器!所以综合排列如下:
render 函数选项  > template 参数  > 外部 HTML
 

Vue 的编译过程——把模板编译成 render 函数

Vue 的编译实际上是指 Vue 把模板编译成 render 函数的过程
 
我们可以通过 Vue.compile 这个实时编译模板的函数来看一看:
用官方文档的例子做个解释:
<div>
  <header>
    <h1>I'm a template!</h1>
  </header>
  <p v-if="message">
    {{message}}
  </p>
  <p v-else>
    No message.
  </p>
</div>

 

  
会被渲染成
function anonymous() {
  with(this){return _c('div',[_m(0),(message)?_c('p',[_v(_s(message))]):_c('p',[_v("No message.")])])}
}

 

回到顶部

beforeMount 和 mounted 钩子函数间的生命周期

 

 

对于这一点,我也感到有些迷惑,百度后之后也没什么头绪,最后我思考的结果是这样的:正因为 render 函数和 template 选项的“优先级”比外部 HTML 要高,所以,最后一般会存在一个外部 HTML 模板被 Vue 实例本身配置的模板所“替代”的过程也就是上图所说的 “replace”
 
(如果大家有不同意见也可以在评论处一起讨论)
 
回到顶部

beforeUpdate 钩子函数和 updated 钩子函数间的生命周期

 

 

在 Vue 中,数据更改会导致虚拟 DOM 重新渲染,并先后调用 beforeUpdate 钩子函数和 updated 钩子函数
 
但要注意一点:重渲染(调用这两个钩子函数)的前提是被更改的数据已经被写入模板中!!(这点很重要)
例如:
var vm = new Vue({
  el: '#app',
  data: {
    number: 1
  },
  template: '<div id="app"><p></p></div>',
  beforeUpdate: function () {
    console.log('调用了 beforeUpdate 钩子函数') },
  updated: function () {
    console.log('调用了 updated 钩子函数') }
})
 
vm.number = 2

 

 

 

控制台上并没有如我们预料那样输出调用两个钩子函数的文本
而当我们改成
var vm = new Vue({
  el: '#app',
  data: {
    number: 1
  },
  // 在模板中使用 number 这个数据
  template: '<div id="app"><p>  {{number}} </p></div>',
  beforeUpdate: function () {
    console.log('调用了 beforeUpdate 钩子函数') },
  updated: function () {
    console.log('调用了 updated 钩子函数') }
})
 
vm.number = 2
 

 

 

 
这个时候,调用两个钩子函数的文本就被输出来了
总之,只有 Vue 实例中的数据被“写入”到我们的模板中,它的改变才可以被 Vue 追踪,重渲染从而调用 beforeUpdate 钩子函数和 updated 钩子函数
 
回到顶部

beforeDestroy 和 destroyed 钩子函数间的生命周期

 

 

beforeDestroy 钩子函数在实例销毁之前调用。在这一步,实例仍然完全可用。
 
destroyed 钩子函数在 Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
 
【注意】就如同调用在 Vue 实例上调用 $mounted 会使暂停的生命周期继续一样,调用 $destroy() 会直接销毁实例