用 watchEffect 实现参数变化自动重拉,核心是将请求逻辑写在回调中并直接读取响应式依赖(如 route.params.id、searchKey.value),Vue 自动追踪;需封装请求函数但不可提前解构响应式值;可同步控制 loading/error 状态,并通过 AbortController 防抖与取消请求。

用 watchEffect 实现“参数变、数据自动重拉”,核心就一条:把请求逻辑写在 watchEffect 回调里,同时在回调中直接读取响应式依赖(比如路由参数、搜索关键词、筛选状态),Vue 会自动追踪并重新执行。
依赖什么,就读取什么
watchEffect 不需要手动声明依赖数组,它靠「响应式读取」自动收集。只要你在回调里访问了某个响应式变量(如 route.params.id、searchKey.value),它就会被监听。
- ✅ 正确:直接读
route.params.id或filterStatus.value - ❌ 错误:把参数先存成普通变量再用(会脱离响应式追踪)
封装请求逻辑,避免重复代码
把 API 调用抽成函数,但注意:函数内部仍要读取响应式变量,不能把值提前解构出来。
const loadData = async () => {
const id = route.params.id; // ✅ 在 watchEffect 内实时读取
if (!id) return;
data.value = await api.getUser(id);
};
然后直接传给 watchEffect:
watchEffect(async (onInvalidate) => {
const pending = loadData();
onInvalidate(() => {
// 可选:取消上一次请求(配合 AbortController 或 cancel token)
});
await pending;
});
处理 loading 和错误状态更自然
因为 watchEffect 是同步注册、异步执行,你可以在回调开头设 loading.value = true,结束时关掉——整个流程完全受控,不依赖额外的副作用管理。
watchEffect(async () => {
loading.value = true;
error.value = null;
try {
data.value = await api.getList(route.query.category, search.value);
} catch (e) {
error.value = e.message;
} finally {
loading.value = false;
}
});
注意防抖和请求中断(进阶但实用)
对于搜索输入这类高频变化,加个简单防抖 + 请求取消,体验更稳:
- 用
ref存当前控制器(AbortController) - 每次进入
watchEffect先 abort 上次请求 - 把
signal传给fetch或 Axios
这样既保持代码简洁,又避免竞态问题。

















