VUE的生命周期

生命周期

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

在Vue的整个生命周期中,它提供了一系列的事件,可以让我们在事件触发时注册js方法,可以让我们用自己注册的js方法控制整个大局,在这些事件响应方法中的this直接指向的是vue的实例。

图解生命周期

特别值得注意的是created钩子函数和mounted钩子函数的区别

每个钩子函数都在啥时间触发

beforeCreate

在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。

created

实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。

beforeMount

在挂载开始之前被调用:相关的 render 函数首次被调用。

mounted

el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。

beforeUpdate

数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。

updated

由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。

当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。

该钩子在服务器端渲染期间不被调用。

beforeDestroy

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

destroyed

Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。 该钩子在服务器端渲染期间不被调用。

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 ><p>模板在templated参数中找到了哟~</p></div>'
})
demo:

 

 

 

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

 

demo:

 

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

 

 
创建Vue实例(包含template参数选项)
new Vue({
  el: '#app',
  template: '<div ><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 ><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 ><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()会直接销毁实例
<think>嗯,用户想了解Vue.js的生命周期及其各个阶段的钩子函数功能。首先,我需要回顾一下Vue生命周期相关知识。根据提供的引用内容,Vue生命周期分为八个阶段,每个阶段都有对应的钩子函数。用户的问题是要详细解释每个阶段和钩子函数的作用,所以我需要按照生命周期的顺序来组织回答。 首先,我应该先介绍生命周期的整体概念,说明它从实例创建到销毁的整个过程,以及钩子函数的作用。然后分阶段介绍每个钩子函数,比如创建阶段、挂载阶段、更新阶段和销毁阶段。每个阶段里有哪些钩子函数,它们的触发时机和用途是什么。比如在创建阶段,有beforeCreate和created,这两个钩子函数分别在实例初始化之后和数据观测建立之前触发,created之后可以进行数据操作,但DOM还未生成。 接下来是挂载阶段的beforeMount和mounted,这两个钩子涉及模板编译和DOM挂载。beforeMount在模板编译完成但尚未挂载到DOM时触发,而mounted在实例挂载到DOM后触发,适合进行DOM操作或第三方库初始化。 然后是更新阶段的beforeUpdate和updated,当数据变化导致DOM重新渲染时触发,beforeUpdate在虚拟DOM打补丁之前,updated在之后。需要注意的是避免在这两个钩子里修改数据,以免导致无限循环。 最后是销毁阶段的beforeDestroy和destroyed,用于清理工作,如移除事件监听或定时器。beforeDestroy在实例销毁前触发,还可以访问实例,而destroyed之后实例完全被销毁。 另外,需要提到Vue 3中的变化,比如使用setup函数替代了之前的钩子,但用户可能还在使用Vue 2,所以需要区分说明。同时,要强调正确使用生命周期钩子的重要性,比如在created中获取数据,在mounted中进行DOM操作,避免在beforeDestroy中遗漏清理导致内存泄漏。 还要考虑用户可能的后续问题,比如生命周期在实际项目中的应用、Vue 2和3的区别、常见错误处理等,提前准备相关问题。确保回答结构清晰,分点说明每个钩子函数,并引用提供的参考资料来支持内容,比如引用[1]到[4]中的描述。同时注意使用正确的LaTeX格式,虽然这个问题可能不涉及数学公式,但如果有需要的地方要正确应用。 现在需要将以上思考整理成一个结构化的回答,分阶段解释每个钩子函数,确保引用正确,并生成相关问题供用户进一步探索。还要检查是否符合用户的要求,比如使用中文,正确的代码块格式(如果有的话),以及引用标识的添加。</think>### Vue.js 生命周期详解及钩子函数功能 Vue.js 生命周期描述了 Vue 实例从创建到销毁的全过程,开发者可通过生命周期钩子函数在特定阶段执行自定义逻辑。以下按阶段详细说明各钩子函数的功能及触发时机: --- #### 一、**创建阶段** 1. **`beforeCreate`** - **触发时机**:实例初始化后,数据观测(data observer)和事件配置前 - **功能**:此时无法访问 `data` 和 `methods` 中的属性,适合初始化非响应式变量 - 代码示例: ```javascript beforeCreate() { console.log(this.message); // undefined } ``` 2. **`created`** - **触发时机**:数据观测已建立,但 DOM 未生成 - **功能**:可访问 `data` 和 `methods`,常用于异步数据请求(如 API 调用) - 示例: ```javascript created() { this.fetchData(); // 调用接口获取数据 } ``` --- #### 二、**挂载阶段** 3. **`beforeMount`** - **触发时机**:模板编译完成,但尚未挂载到 DOM - **功能**:最后一次操作虚拟 DOM 的机会,但实际 DOM 元素不可见 4. **`mounted`** - **触发时机**:实例挂载到 DOM 后 - **功能**:可操作真实 DOM,适合初始化第三方库(如图表库) - 示例: ```javascript mounted() { this.initChart(); // 渲染图表到 DOM } ``` --- #### 三、**更新阶段** 5. **`beforeUpdate`** - **触发时机**:数据变化后,虚拟 DOM 重新渲染前 - **功能**:可获取数据更新前的 DOM 状态 6. **`updated`** - **触发时机**:虚拟 DOM 重新渲染并应用补丁后 - **注意**:避免在此阶段修改数据,可能导致无限循环 --- #### 四、**销毁阶段** 7. **`beforeDestroy`** - **触发时机**:实例销毁前 - **功能**:清理定时器、解绑事件等资源释放操作 - 示例: ```javascript beforeDestroy() { clearInterval(this.timer); // 清除定时器 } ``` 8. **`destroyed`** - **触发时机**:实例销毁后 - **功能**:所有子实例和事件监听器已被移除 --- ### 生命周期图示 ```plaintext 创建阶段 → 挂载阶段 → 更新阶段 → 销毁阶段 │ │ │ │ beforeCreate beforeMount beforeUpdate beforeDestroy │ │ │ │ created mounted updated destroyed ``` --- ### 注意事项 - **Vue 3 变化**:组合式 API 中使用 `setup()` 替代 `beforeCreate` 和 `created`[^3] - **性能优化**:在 `mounted` 中避免同步修改 DOM,可能导致重复渲染 - **内存泄漏**:务必在 `beforeDestroy` 中清理全局事件监听器 --- §§ 1. Vue 生命周期钩子函数在实际项目中如何选择使用? 2. Vue 2 和 Vue 3 的生命周期有哪些区别? 3. 在 `created` 和 `mounted` 中请求数据有什么区别? 4. 为什么在 `updated` 钩子中修改数据可能导致问题? [^1]: Vue.js组件生命周期详解 [^2]: Vue实例生命周期与功能实现 : Vue.js 核心框架与生命周期阶段 [^4]: Vue实例创建到销毁的全过程解析
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值