在vue开发中,你是否遇到过这些问题:
在created钩子中操作dom却获取不到元素?
父子组件的mounted钩子到底谁先执行?
在beforeDestroy中清理资源却发现组件已被移除?
这些问题的核心在于对Vue生命周期执行顺序的理解不足。本文将深入解析Vue2和Vue3的生命周期流程,帮助你在实际开发中精准掌控组件行为。
关键阶段详解:
创建阶段
beforeCreate() {
// 此时无法访问data和methods
console.log('beforeCreate:', this.message) // undefined
}
created() {
// 可访问数据但DOM未生成
console.log('created:', this.message) // 数据可用
console.log('DOM:', this.$el) // undefined
}
挂载阶段
beforeMount() {
// 模板编译完成但未挂载到页面
console.log('beforeMount:', this.$el.innerhtml) // 旧内容
}
mounted() {
// DOM完全可用,可进行DOM操作
console.log('mounted:', this.$el.textContent) // 渲染后内容
}
更新阶段
beforeUpdate() {
// 数据已改变但DOM未更新
console.log('beforeUpdate DOM:', this.$el.textContent) // 旧内容
}
updated() {
// DOM更新完成
console.log('updated DOM:', this.$el.textContent) // 新内容
}
销毁阶段
beforeDestroy() {
// 组件销毁前,可清理定时器
console.log('beforeDestroy:', this._isBeingDestroyed) // false
clearInterval(this.timer)
}
destroyed() {
// 组件完全销毁
console.log('destroyed:', this._isBeingDestroyed) // true
}
Vue2到Vue3映射关系:
Vue2选项式API | Vue3组合式API |
---|---|
beforeCreate | 使用setup()代替 |
created | 使用setup()代替 |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
组合式API执行顺序示例:
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
export default {
setup() {
console.log('setup - 替代created')
onBeforeMount(() => {
console.log('onBeforeMount')
})
onMounted(() => {
console.log('onMounted')
})
// 其他钩子同理...
return {}
}
}
组件嵌套时的执行流程:
flowchart TD
A[父beforeCreate] --> B[父created]
B --> C[父beforeMount]
C --> D[子beforeCreate]
D --> E[子created]
E --> F[子beforeMount]
F --> G[子mounted]
G --> H[父mounted]
实际代码验证:
<!-- Parent.vue -->
<script>
export default {
beforeCreate() { console.log('父 beforeCreate') },
created() { console.log('父 created') },
beforeMount() { console.log('父 beforeMount') },
mounted() { console.log('父 mounted') },
}
</script>
<template>
<Child />
</template>
<!-- Child.vue -->
<script>
export default {
beforeCreate() { console.log('子 beforeCreate') },
created() { console.log('子 created') },
beforeMount() { console.log('子 beforeMount') },
mounted() { console.log('子 mounted') },
}
</script>
输出顺序:
父 beforeCreate
父 created
父 beforeMount
子 beforeCreate
子 created
子 beforeMount
子 mounted
父 mounted
created中发起异步请求
created() {
fetchData().then(data => {
// 此时可能已进入mounted阶段
this.data = data
})
}
mounted中的DOM操作陷阱
mounted() {
// 若子组件异步加载,此时可能未渲染
this.$nextTick(() => {
// 确保DOM更新后执行
this.initThirdPartyLib()
})
}
更新阶段的数据竞态问题
updated() {
// 避免在此处直接修改状态,可能导致无限循环
// 正确做法:使用计算属性或侦听器
}
错误1:在created中操作DOM
created() {
// 错误!此时DOM尚未创建
document.getElementById('myEl').style.color = 'red'
}
✅ 解决方案:将DOM操作移至mounted钩子
错误2:忽略异步组件的生命周期
<template>
<AsyncComponent v-if="show" />
</template>
<script>
export default {
methods: {
loadComponent() {
this.show = true
// 错误!此时异步组件可能尚未加载完成
this.$nextTick(() => {
// 正确:等待组件完全挂载
})
}
}
}
</script>
错误3:在beforeDestroy中访问已销毁元素
beforeDestroy() {
// 危险操作:此时DOM元素可能已被移除
this.$el.removeEventListener('click', this.handler)
}
✅ 解决方案:在mounted中添加监听,在beforeUnmount中移除
数据初始化
created() {
// 初始化非响应式数据
this.timer = null
}
API请求时机
created() {
// 尽早发起请求,减少用户等待时间
this.loadUserData()
}
第三方库初始化
mounted() {
// DOM就绪后初始化
this.chart = echarts.init(this.$el)
},
beforeUnmount() {
// 清理资源防止内存泄漏
this.chart.dispose()
}
性能敏感操作
updated() {
// 避免在此处执行重操作
// 使用watch深度监听替代
}
keep-alive组件专属钩子
activated() {
// 组件被激活时调用
this.startAnimation()
},
deactivated() {
// 组件被停用时调用
this.pauseAnimation()
}
错误捕获钩子
errorCaptured(err, vm, info) {
// 捕获子组件错误
logErrorToService(err)
return false // 阻止错误继续向上传播
}
创建阶段:
beforeCreate:避免操作数据
created:安全访问数据,可发起API请求
挂载阶段:
beforeMount:极少使用
mounted:执行DOM操作,初始化第三方库
更新阶段:
beforeUpdate:获取更新前DOM状态
updated:避免修改响应式数据
销毁阶段:
beforeUnmount(Vue3)/beforeDestroy(Vue2):清理定时器、事件监听
unmounted(Vue3)/destroyed(Vue2):确认组件已卸载
父子组件顺序口诀:
父创建 → 子创建 → 子挂载 → 父挂载
父更新 → 子更新 → 子完成 → 父完成
父销毁 → 子销毁 → 子完成 → 父完成
理解生命周期执行顺序是成为Vue高级开发者的必备技能。合理利用各生命周期钩子,既能避免常见错误,又能优化组件性能。建议在开发复杂组件时,配合console.log输出各阶段状态,加深对执行流程的理解。
接下来我们会详细分析下如何完成由多个组件组成一个复用组件的开发流程。本节我们主要要完成这样一个列表功能,每一行的列表是一个组件,列表内可能出现按钮组件或者箭头组件,点击按钮组件可以自定义事件
JavaScript运行三部曲:语法分析、预编译、解释执行。语法分析很简单,就是引擎检查你的代码有没有什么低级的语法错误; 解释执行顾名思义便是执行代码了; 预编译简单理解就是在内存中开辟一些空间,存放一些变量与函数 ;
开发准备:了解产品和设计,提出疑问和见解,技术调研和培训,预算人力和时间。开发过程:职责任务,页面开发,提取剥离
vue是通过rollup来进行构建的,同样的构建工具webpack更强大一些,可以处理图片、 css、js等;但是rollup只做js的处理,相比之下更轻量, 所以rollup更适合js框架的打包,总共有三个版本的构建
前端开发经常会遇到这样的情况,项目经理莫名奇妙发了个会议邀请,然后一股脑把产品下阶段的需求讲完,开发听得云里雾里,心里吐槽一堆细节产品自己没理清,居然在这问前端要多久
我相信很多前端初学者一开始都会被执行上下文这个概念弄晕,或者说似懂非懂。对于工作两年的我来说,说来实在惭愧,虽然知道它大概是什么,但总觉得没有一个更为清晰的认识(无法把它的工作过程描述清楚)
流程控制作用:控制代码的执行顺序;分类:(1) 顺序结构:从上到下依次执行代码语句(2) 分支/选择结构;if语句简单if结构,注意 : 除零值以外,其他值都为真,以下条件为假值false
事件流程分为三个阶段:捕获阶段、目标阶段、冒泡阶段。dom2级事件可以重复绑定,在高级浏览器中的执行顺序是从上至下。在ie8以下浏览器中是倒叙执行,但是当attachEvent和dom0级一起执行时
JS 程序的入口,将当前 APP 对象注册到 AppRegistry 组件中, AppRegistry 组件是 js module;我们新建一个RN的项目,在原生代码中会生成 MainActivity 和 MainApplication 两个 Java 类。顾名思义
在运维过程中,网站部署是运维的工作之一。传统的网站部署的流程大致分为:需求分析 --> 原型设计 --> 开发代码 --> 提交代码 --> 内网部署 --> 内网测试 --> 确认上线 --> 备份数据 --> 外网更新 --> 外网测试 --> 发布完成
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!