生命周期 mounted vs 方法 如何选择
1. 时机控制问题
methods 中的方法需要手动调用,而 mounted 是自动执行的特定时机。
<template>
<div ref="chart"></div>
</template>
<script>
export default {
data() {
return {
chart: null
};
},
// 错误示例:在 methods 中初始化 DOM 操作
methods: {
initChart() {
// 问题1:什么时候调用这个方法?
// 问题2:如果调用时 DOM 还没渲染怎么办?
this.chart = echarts.init(this.$refs.chart); // 可能报错
}
},
// 正确示例:在 mounted 中自动执行
mounted() {
// 确保此时 DOM 已经渲染完成
this.chart = echarts.init(this.$refs.chart);
this.chart.setOption({/*...*/});
}
}
</script>
2. DOM 可用性保证
<script>
export default {
methods: {
// 这个方法可能在 DOM 渲染前被调用
focusInput() {
this.$refs.myInput.focus(); // 可能为 undefined
},
// 这个方法可能在 DOM 渲染后被调用
safeFocusInput() {
// 需要先检查 DOM 是否存在
if (this.$refs.myInput) {
this.$refs.myInput.focus();
} else {
console.warn('DOM 还未准备好');
}
}
},
created() {
// 在 created 阶段调用方法
this.focusInput(); // 会报错
},
mounted() {
// 在 mounted 阶段调用,安全
this.$refs.myInput.focus(); // 安全
}
}
</script>
3. 实际场景对比
场景:初始化一个图表库
<script>
// 错误做法:依赖 methods
export default {
methods: {
initECharts() {
// 问题:这个方法需要在多个地方调用
const chart = echarts.init(this.$el);
chart.setOption(this.options);
// 还需要监听窗口变化
window.addEventListener('resize', () => {
chart.resize();
});
// 还需要在组件销毁时清理
this.$once('hook:beforeDestroy', () => {
window.removeEventListener('resize', chart.resize);
chart.dispose();
});
}
},
created() {
// 不能在这里调用,DOM 不存在
// this.initECharts(); // 报错
},
// 需要在模板中调用?
mounted() {
// 还是要在这里调用
this.initECharts(); // 那为什么不在 mounted 里直接写
}
};
</script>
正确做法:使用 mounted
<script>
export default {
data() {
return {
chart: null
};
},
mounted() {
// 一次性初始化,逻辑集中
this.chart = echarts.init(this.$el);
this.chart.setOption(this.options);
// 事件监听
this.handleResize = () => this.chart.resize();
window.addEventListener('resize', this.handleResize);
},
beforeDestroy() {
// 集中清理
window.removeEventListener('resize', this.handleResize);
if (this.chart) {
this.chart.dispose();
}
}
};
</script>
4. 为什么不在 methods 里随意调用的原因
| 原因 | 说明 | 示例 |
|---|---|---|
| 时机不确定性 | 不知道什么时候 DOM 准备好了 | 可能在 created 中调用,但 DOM 未渲染 |
| 重复执行风险 | 可能被多次调用导致重复初始化 | 图表被重复初始化,事件重复绑定 |
| 逻辑分散 | 初始化和清理逻辑分散在不同地方 | 初始化在 methods,清理在 beforeDestroy |
| 生命周期关联 | 有些操作需要精确的生命周期时机 | 只在组件挂载时执行一次的操作 |
5. 什么情况下应该在 methods 中执行
并不是所有操作都不应该在 methods 中,以下情况适合:
<script>
export default {
mounted() {
// 初始加载数据
this.loadData();
// 初始化第三方库
this.map = new AMap.Map('map');
},
methods: {
// 适合在 methods 中:用户交互触发
handleClick() {
this.loadData(); // 重新加载数据
},
// 适合在 methods 中:可重复调用的操作
loadData() {
axios.get('/api/data').then(res => {
this.data = res.data;
});
},
// 适合在 methods 中:更新已存在的实例
updateMap() {
if (this.map) {
this.map.setCenter([116.39, 39.9]);
}
}
}
};
</script>
最佳原则
1. 初始化操作放在 mounted
mounted() {
// DOM 相关初始化
this.initThirdPartyLibrary();
// 一次性的事件监听
window.addEventListener('resize', this.handleResize);
// 获取初始数据(如果需要 DOM)
if (this.needDOM) {
this.fetchInitialData();
}
}
2. 可复用的逻辑放在 methods
methods: {
// 可以被多次调用的方法
fetchData(params) {
return axios.get('/api/data', { params });
},
// 用户交互触发的方法
handleUserAction() {
// ...
}
}
3. 清理操作放在 beforeDestroy
beforeDestroy() {
// 清理事件监听
window.removeEventListener('resize', this.handleResize);
// 销毁第三方库实例
if (this.chart) {
this.chart.dispose();
}
}
总结
关键区别:
-
mounted:自动执行于特定生命周期,保证 DOM 已存在 -
methods:手动调用,调用时机不确定
简单记忆:
-
如果操作依赖 DOM → 用
mounted -
如果操作需要执行一次且在组件挂载时 → 用
mounted -
如果操作由用户交互触发或需要重复调用 → 用
methods -
如果操作既要在初始化执行又要能重复执行 →
mounted中调用methods的方法
<script>
export default {
mounted() {
// 初始化:保证只执行一次,DOM 已存在
this.init();
},
methods: {
// 可复用:既能被 mounted 调用,也能被其他方法调用
init() {
// 初始化逻辑
},
// 用户交互:由事件触发
handleClick() {
// 处理点击
}
}
};
</script>
所以,之所以选择 mounted 而不是在 methods 里随意调用,主要是为了确保正确的执行时机和代码的组织清晰性。
1237

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



