一、核心定位:组件生命周期的“黄金初始化时机”
created 钩子在 Vue 组件实例被完全创建后同步调用。您可以将其理解为组件“肉身”已经构造完成,但还未“挂载”到 DOM 上的关键时刻。
为了更直观地理解它在整个组件生命周期中的位置,请先参看下图:

从上图可以清晰地看到,created 发生在响应式数据初始化之后,DOM 挂载之前。这个时机点的特性决定了它的核心用途和局限性。
二、深度原理:在初始化链条中的关键作用
要理解 created,必须了解 Vue 实例的完整初始化流程。下图展示了 created 钩子在整个组件初始化流程中的关键作用:

关键解读:
在 Init State 阶段,Vue 完成了以下关键操作,这正是 created 中能访问到响应式数据的原因:
- 将
data对象变为响应式,并代理到实例上(this.xxx访问)。 - 处理
props、methods、computed、watch等选项。 - 正是这些工作的完成,使得
created成为第一个可以安全操作数据的生命周期钩子。
三、created 的核心职责与最佳实践
基于其“数据已就绪,DOM 未生成”的特性,created 钩子最适合完成以下几类任务:
1. 异步数据获取(首屏优化)
这是 created 最经典的用途。为了尽快减少用户白屏时间,应尽早发起异步请求。
export default {
data() {
return {
userInfo: null,
productList: []
};
},
async created() {
// 并行发起多个异步请求,优化首屏加载
try {
const [userResponse, productsResponse] = await Promise.all([
this.$api.getUserInfo(),
this.$api.getProducts()
]);
this.userInfo = userResponse.data;
this.productList = productsResponse.data;
} catch (error) {
console.error('数据获取失败:', error);
}
}
};
为什么不在 mounted 中获取?
- 更早触发:
created比mounted执行得更早,能更早获取数据,缩短首屏时间。 - DOM 非必需:数据获取是逻辑操作,不依赖 DOM。在
mounted中获取会无谓地延迟请求。
2. 初始化组件状态与监听事件
export default {
created() {
// 基于 props 初始化内部状态
this.internalValue = this.value || this.defaultValue;
// 初始化非响应式数据(避免不必要的响应式开销)
this.staticConfig = Object.freeze({ MAX_COUNT: 100 });
// 监听全局事件总线
this.$eventBus.$on('global-event', this.handleGlobalEvent);
},
beforeUnmount() {
// 必须在组件销毁时移除监听,防止内存泄漏!
this.$eventBus.$off('global-event', this.handleGlobalEvent);
}
};
3. 执行一次性的计算或设置
export default {
created() {
// 执行一次性的计算,结果缓存到数据中
this.initialHash = this.calculateInitialHash(this.initialData);
// 设置定时器
this.autoSaveTimer = setInterval(this.autoSave, 30000);
},
beforeUnmount() {
// 必须清理定时器!
clearInterval(this.autoSaveTimer);
}
};
四、组合式 API 中的对应物:setup()
在 Vue 3 的组合式 API 中,created 钩子没有直接的等价物,因为它的逻辑被整合到了 setup() 函数中。
心智模型转换:
- 选项式 API:
created是一个特定的“时间点”。 - 组合式 API:
setup()中顶层的同步代码就是created的逻辑。
// 选项式 API
export default {
data() { return { count: 0 }; },
created() {
console.log('created:', this.count); // 0
this.fetchData();
}
};
// 组合式 API
import { ref, onMounted } from 'vue';
export default {
setup() {
const count = ref(0);
// 这里的同步代码相当于 created
console.log('setup同步代码:', count.value); // 0
fetchData(); // 相当于在 created 中调用
// 如果需要 mounted 的逻辑,要显式使用 onMounted
onMounted(() => {
console.log('mounted');
});
return { count };
}
};
五、专家级注意事项与性能优化
1. 内存泄漏风险
created 中创建的监听器、定时器、事件监听等必须在 beforeUnmount/unmounted 中清理。
export default {
created() {
this.intervalId = setInterval(() => {}, 1000);
window.addEventListener('resize', this.handleResize);
},
beforeUnmount() {
clearInterval(this.intervalId);
window.removeEventListener('resize', this.handleResize);
}
};
2. 异步操作与组件卸载的竞争条件
如果组件在数据返回前被销毁,异步回调中设置数据会导致内存泄漏。
export default {
data() { return { data: null }; },
created() {
let isMounted = true; // 标志位
this.$api.getData().then(result => {
if (isMounted) { // 检查组件是否仍挂载
this.data = result;
}
});
this.$once('hook:beforeUnmount', () => {
isMounted = false; // 组件卸载时标记为 false
});
}
};
3. 避免阻塞渲染
created 是同步执行的,如果其中有繁重的同步计算,会阻塞组件的渲染进程。
// ❌ 避免:繁重同步计算
created() {
// 这会阻塞组件渲染
this.heavyData = this.calculateHeavyStuff();
}
// ✅ 推荐:使用计算属性(惰性求值)或异步处理
computed: {
heavyData() { return this.calculateHeavyStuff(); }
}
// 或
async created() {
// 使用 requestIdleCallback 或拆分为小任务
this.heavyData = await this.calculateAsync();
}
总结:created 的专家级理解
| 维度 | 深度分析 |
|---|---|
| 定位 | 数据响应式初始化完成,DOM 未生成的“黄金初始化时机” |
| 核心用途 | 异步数据获取、事件监听、一次性初始化、状态设置 |
| 优势 | 比 mounted 更早,适合不依赖 DOM 的逻辑,优化首屏 |
| 局限 | 无法操作 DOM,异步回调需处理组件销毁的竞争条件 |
| 组合式 API | 被整合到 setup() 函数的同步执行部分 |
| 性能关键 | 避免同步阻塞,及时清理副作用防止内存泄漏 |
将 created 视为组件的“数据准备阶段”。在这个阶段完成所有不依赖 DOM 的初始化工作,为后续的渲染和交互打下坚实基础。理解其在 Vue 初始化流程中的精确位置,能帮助您写出更高效、更健壮的 Vue 应用。
1602

被折叠的 条评论
为什么被折叠?



