详解VUE生命周期

在这里插入图片描述
红边圆角空心矩形内的都是对应的Vue实例的钩子函数

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

在这里插入图片描述
实例、组件通过new Vue() 创建出来之后会初始化事件和生命周期,然后就会执行beforeCreate钩子函数,这个时候,数据还没有挂载,只是一个空壳,无法访问到数据和真实的dom,一般不做操作。

在beforeCreate和created钩子函数之间的生命周期之间,进行初始化事件,进行数据的观测。

在created的时候,组件实例已经创建完成,数据已经和data属性进行绑定(放在data中的属性当值发生改变的同时,视图也会改变),但是DOM还未生成,$el属性还未出现(若存在)。这个时候已经可以使用到数据,也可以更改数据,在这里更改数据不会触发updated函数,在这里可以在渲染前倒数第二次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取。

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

el选项的有无对生命周期过程的影响
在这一阶段,首先会判断对象是否有el选项。如果有的话就继续向下编译,如果没有el选项,则停止编译,也就意味着停止了生命周期,直到在该vue实例上调用vm.$mount(el)。

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
    <div>hello world</div>
    <script>
        new Vue({
          el: '#app',
          beforeCreate: function () {
            console.log('调用了beforeCreat钩子函数')
          },
          created: function () {
            console.log('调用了created钩子函数')
          },
          beforeMount: function () {
            console.log('调用了beforeMount钩子函数')
          },
          mounted: function () {
            console.log('调用了mounted钩子函数')
          }
        })
    </script>
</body>
</html>

在这里插入图片描述
从上图结果可以看到,在el选项填写且正确的时候,生命周期将正常进行。

而当我们把el去掉之时

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
    <div>hello world</div>
    <script>
        new Vue({
          beforeCreate: function () {
            console.log('调用了beforeCreat钩子函数')
          },
          created: function () {
            console.log('调用了created钩子函数')
          },
          beforeMount: function () {
            console.log('调用了beforeMount钩子函数')
          },
          mounted: function () {
            console.log('调用了mounted钩子函数')
          }
        })
    </script>
</body>
</html>

在这里插入图片描述
可以看到,生命周期的钩子函数执行到created就结束了。
而当我们不加el选项,但是手动执行vm.$mount(el)方法的话,也能够使暂停的生命周期进行下去,例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
    <div>hello world</div>
    <script>
       let 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')
    </script>
</body>
</html>

在这里插入图片描述
此时可以看到,这个时候虽然对象中没有el参数,但通过$mount(el)动态添加的方式,也能够使生命周期顺利进行。

template参数选项的有无对生命周期的影响
如果Vue实例对象中有template参数选项,则将其作为模板编译成render函数。

如果没有template参数选项,则将外部的HTML作为模板编译(template),也就是说,template参数选项的优先级要比外部的HTML高。
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
    <div id="app">hello world</div>
    <script>
    new Vue({
      el: '#app',
      template: '<div id="app"><p>模板在templated参数中</p></div>'
    })
    </script>
</body>
</html>

运行此代码:会得到“模板在templated参数中”的结果;而把js中的template注释掉之后,则会得到“hello world”的结果

在created钩子函数和beforeMount之间,开始找实例或者组件对应的模板,编译模板为虚拟dom放入到render函数中准备渲染,然后执行beforeMount钩子函数。在这个函数中虚拟dom已经创建完成,马上就要渲染,在这里也可以更改数据,不会触发updated,在这里可以在渲染前最后一次更改数据的机会,不会触发其他的钩子函数,一般可以在这里做初始数据的获取。

为什么判断el要发生在判断template前面?
因为Vue需要通过el的“选择器”找到对应的template。总结一下上述的过程,Vue通过el参数去找到对应的template。然后,根据el参数给出的“选择器”,首先去Vue实例对象本身的template选项参数中找,如果没有template参数,则到外部HTML中寻找,找到后将模板编译成render函数。
.实际上,在Vue中,有render函数这个选项,它以createElement作为参数,做渲染操作。当然你也可以不调用createElement,而直接嵌入JSX
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钩子函数间的生命周期

由上文可知,beforeMount在实例挂载到DOM开始之前被调用,beforeMount之前,会找到对应的template,并编译成render函数。

接下来开始render,渲染出真实dom,然后执行mounted钩子函数,此时,组件已经出现在页面中,数据、真实dom都已经处理好了,事件都已经挂载好了,可以在这里操作真实dom等事情
在这里插入图片描述
因为render函数和template选项的“优先级”比外部HTML要高,所以,最后一般会存在一个外部HTML模板被Vue实例本身配置的模板所“替代”的过程也就是上图所说的 “replace”。

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

在Vue中,数据更改会导致虚拟 DOM 重新渲染,并先后调用beforeUpdate钩子函数和updated钩子函数。

当组件或实例的数据更改之后,会立即执行beforeUpdate,然后vue的虚拟dom机制会重新构建虚拟dom与上一次的虚拟dom树利用diff算法进行对比之后重新渲染。

当更新完成后,执行updated,数据已经更改完成,dom也重新render完成,可以操作更新后的虚拟dom。
重渲染(调用这两个钩子函数)的前提是被更改的数据已经被写入模板中
比如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
    <div id="app">hello world</div>
    <script>
    let 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
    </script>
</body>
</html>

在这里页面不会显示任何内容,而如果是下面的代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
    <div id="app">hello world</div>
    <script>
    let vm = new Vue({
      el: '#app',
      data: {
        number: 1
      },
      template: '<div id="app"><p>{{ number }}</p></div>',
      beforeUpdate: function () {
        console.log('调用了beforeUpdate钩子函数')
      },
      updated: function () {
        console.log('调用了updated钩子函数')
      }
    })
   
    vm.number = 2
    </script>
</body>
</html>

页面就会显示出“2”, 只有Vue实例中的数据被“写入”到我们的模板中,它的改变才可以被Vue追踪,重渲染从而调用 beforeUpdate钩子函数和updated钩子函数。

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

beforeDestroy钩子函数在实例销毁之前调用。在这一步,实例仍然完全可用。当经过某种途径调用$destroy方法后,立即执行beforeDestroy,一般在这里做一些善后工作,例如清除计时器、清除非指令绑定的事件等等。

destroyed钩子函数在Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

就如同调用在Vue实例上调用$mounted会使暂停的生命周期继续一样,

调用$destroy()会直接销毁实例。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值