问题原因分析
typescript
import { onMounted, ref } from 'vue';
export default {
setup() {
const data = ref(null);
// 异步获取数据
fetchData().then(res => {
data.value = res;
});
onMounted(() => {
// 这里获取不到数据!
console.log(data.value); // null
});
return { data };
}
}
问题核心在于 执行时序:
setup函数是同步执行的- 异步请求需要时间(网络请求通常是几十毫秒到几秒)
onMounted在组件挂载后立即执行(此时异步请求可能尚未完成)
正确解决方案
方案1:在 onMounted 中发起请求(推荐)
typescript
import { onMounted, ref } from 'vue';
export default {
setup() {
const data = ref(null);
onMounted(async () => {
// 确保在挂载后才发起请求
data.value = await fetchData();
// 此时可以安全使用数据
console.log(data.value);
});
return { data };
}
}
方案2:使用 watch 监听数据变化
typescript
import { onMounted, ref, watch } from 'vue';
export default {
setup() {
const data = ref(null);
// 在setup中发起请求
fetchData().then(res => {
data.value = res;
});
// 监听数据变化
watch(data, (newVal) => {
if (newVal) {
// 数据到达后执行操作
console.log('数据已加载:', newVal);
}
});
onMounted(() => {
// 直接显示加载状态
console.log('组件已挂载,等待数据...');
});
return { data };
}
}
方案3:使用异步生命周期钩子(高级)
typescript
import { onMounted, ref } from 'vue';
export default {
async setup() {
const data = ref(null);
// 在setup中发起请求但等待结果
data.value = await fetchData();
onMounted(() => {
// 此时数据已准备就绪
console.log(data.value);
});
return { data };
}
}
生命周期执行时序图
组件初始化
│
├─> setup() 同步执行
│ │
│ ├─> 发起异步请求(未完成)
│ │
│ └─> 注册 onMounted 回调
│
├─> 模板编译/挂载
│
└─> onMounted() 执行
│
│ ❌ 此时数据尚未返回
│
├─> 100ms后 异步请求完成 → 数据更新
│
└─> 触发重新渲染