Vue2里的created钩子是干啥的?咋用?
咱在学Vue2的时候,肯定绕不开生命周期钩子,其中created钩子更是经常用到,好多刚接触的小伙伴会疑惑,created到底在啥时候执行?能用来做啥?和mounted这些钩子有啥不一样?今天就唠唠Vue2里created钩子的那些事儿,把这些问题一个个掰碎了讲明白。
created钩子啥时候执行?
要搞懂created的执行时机,得先回忆Vue实例的创建流程,Vue实例从开始创建到最终渲染到页面,会经历一系列“生命周期阶段”,每个阶段对应一个钩子函数,让咱能在特定时机插手逻辑。
created钩子处于实例初始化完成后、DOM还没挂载的阶段,Vue会先做这些事:初始化事件系统、开启数据劫持(把data里的属性变成响应式)、处理options里的配置(比如methods、computed这些),等这些基础工作做完,就会触发created钩子。
这时候有两个关键状态:一是data和methods已经能被访问了(因为初始化完成),二是$el还没生成(DOM元素没挂载,所以没法操作DOM),举个例子,你在created里打印this.data
里的某个属性,能正常输出;但要是想通过document.querySelector
找页面元素,肯定找不到——因为这时候元素还没渲染到页面上呢。
created里适合做哪些事儿?
既然知道了created的执行时机,那哪些场景适合用它呢?下面这几类操作特别常见:
发起异步数据请求
很多页面需要从后端接口拿数据,比如列表页、详情页,这时候在created里发请求特别合适——因为这时候this
能访问到data和methods,请求回来的数据可以直接存到data里,触发页面响应式更新,而且请求不需要依赖DOM(比如列表数据只需要接口返回,和页面元素长啥样没关系),早发请求能让页面加载更快。
举个实际例子:做一个博客列表页,在created里写:
created() { this.fetchArticleList() // fetchArticleList是methods里的方法,负责调接口拿数据 }
这样页面初始化时就开始请求数据,等数据回来后,Vue自动更新页面渲染列表。
初始化依赖数据
有些页面需要根据路由参数、用户信息等,预先处理一些数据,比如详情页根据路由传的id,初始化要展示的内容;或者根据用户权限,决定某些按钮是否显示,这些逻辑放在created里很顺手,因为能拿到this.$route
(路由信息)、this.$store
(Vuex数据)这些。
比如商品详情页,根据路由id请求商品信息:
created() { const productId = this.$route.params.id this.getProductDetail(productId) // 调接口拿商品详情 }
全局事件的监听与逻辑处理
如果用了事件总线(比如Vue.prototype.$bus = new Vue()
),在created里监听全局事件很常见,因为页面创建后需要响应某些全局通知,比如购物车更新、用户登录状态变化,要记得在beforeDestroy
里把这些监听销毁,不然容易内存泄漏。
举个例子:监听购物车商品数量变化
created() { this.$bus.$on('cartUpdate', (newCount) => { this.cartCount = newCount // 把全局事件里的数量更新到当前组件data }) }, beforeDestroy() { this.$bus.$off('cartUpdate') // 销毁监听,避免重复触发 }
created和mounted有啥区别?
很多新手会把created和mounted搞混,其实核心区别就在DOM是否挂载上,咱拆成两点说:
执行时机不同
created在“DOM挂载前”执行,这时候页面上还没有对应的DOM元素;mounted在“DOM挂载后”执行,$el已经渲染到页面了,生命周期顺序是:created → beforeMount → mounted
,所以mounted是created之后、DOM渲染完成的阶段。
能做的事儿不同
因为DOM是否存在,导致两者适合的操作天差地别:
- created:主打“不依赖DOM的逻辑”,比如发请求、处理路由参数、初始化数据、绑定全局事件。
- mounted:主打“依赖DOM的操作”,比如用
refs
获取DOM元素(this.$refs.xxx
)、初始化第三方插件(像ECharts、富文本编辑器,这些需要先有DOM容器才能初始化)、操作DOM样式/结构(比如修改元素的innerHTML
、设置焦点)。
举个直观例子:如果想初始化一个ECharts图表,得先有个div
当容器,这时候ECharts初始化代码就必须放在mounted里——因为created时div
还没渲染,ECharts找不到容器会报错,而如果只是调接口拿图表需要的数据,那放created里更高效。
使用created要注意啥?
虽然created很好用,但要是不注意这些点,容易踩坑:
别在created里搞DOM操作
前面说了,created时DOM还没挂载,这时候去改元素的内容、样式,完全没效果,还可能让代码逻辑混乱,比如你想在created里给某个按钮加个点击事件,用document.querySelector('#btn').addEventListener(...)
,这时候根本找不到#btn
这个元素,代码直接报错,这种DOM相关的操作,乖乖放到mounted里做。
异步请求要处理加载状态
在created里发请求时,页面可能需要显示“加载中”的状态,这时候要在data里搞个loading
变量,请求前设为true
,请求结束(成功或失败)后设为false
,不然用户看页面一直空白,还以为卡了。
比如这样写:
data() { return { list: [], loading: false } }, created() { this.loading = true this.$axios.get('/api/list').then(res => { this.list = res.data this.loading = false }).catch(err => { console.error(err) this.loading = false }) }
注意this的指向问题
在created里写函数时,别乱用箭头函数,因为箭头函数没有自己的this
,它的this
是继承外层作用域的,如果在methods里用箭头函数当方法,或者在created里用箭头函数写回调,很可能导致this
不是Vue实例,拿不到data、methods这些。
错误示例:
methods: { fetchData: () => { // 箭头函数,this不是Vue实例 this.$axios.get(...) // 这里this是window,会报错 } }, created() { this.fetchData() // 调用就会出错 }
正确做法是用普通函数:
methods: { fetchData() { // 普通函数,this指向Vue实例 this.$axios.get(...) } }, created() { this.fetchData() }
created在实际项目中的典型场景
光说理论太虚,咱看几个真实项目里的用法,更有感觉:
场景1:用户权限验证
很多后台管理系统,每个页面都要验证用户是否登录、有没有权限访问,可以在created里检查token是否有效:
created() { const token = localStorage.getItem('token') if (!token) { this.$router.push('/login') // 没token,跳登录页 return } this.checkPermission() // 调接口验证token权限 }
场景2:表单初始化(下拉选项、默认值)
比如添加商品的表单,下拉选项(比如分类、品牌)需要从接口获取,在created里请求这些选项数据,填充到data里的下拉列表:
data() { return { categoryOptions: [], // 分类下拉选项 brandOptions: [] // 品牌下拉选项 } }, created() { this.getCategoryOptions() // 调接口拿分类数据 this.getBrandOptions() // 调接口拿品牌数据 }
场景3:结合Vuex初始化数据
如果用了Vuex管理全局状态,created里可以触发action,把数据同步到Vuex和当前组件,比如用户信息:
created() { this.$store.dispatch('user/fetchUserInfo').then(() => { this.userInfo = this.$store.state.user.info // 把Vuex里的用户信息同步到组件data }) }
Vue2的created钩子是咱在实例初始化后、DOM挂载前操作数据和逻辑的好时机,它适合发请求、处理初始化逻辑、绑定全局事件这些不依赖DOM的操作,和mounted分工明确,只要记住它的执行时机、适用场景和注意事项,就能在项目里用得顺手,让组件的生命周期逻辑更清晰~
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。