nextTick
/**
* 屏蔽标志(用于阻止程序修改分页参数时引发的不必要查询)
* - 重置时使用
* - 查询前将 current 重置为 1 时使用
*/
const isResetting = ref(false);
/**
* 获取交接分页
*/
const fetchHandoverPage = async () => {
initData();
try {
isMasterLoading.value = true;
// 屏蔽分页变化触发的查询(重置 current 时可能触发 @change)
isResetting.value = true;
queryRequest.value.current = 1;
// ⏳ 等待分页组件更新完成,确保分页组件的微任务 change 已被拦截
await nextTick();
isResetting.value = false;
const result = await queryHandoverPageForReceive(queryRequest.value);
handovers.value = result.data.rows;
total.value = result.data.total;
} catch (error) {
handovers.value = [];
} finally {
isMasterLoading.value = false;
}
};
/**
* 分页改变
*/
const handlePageChange = async (currentPage: number, pageSize: number) => {
// 若正处于重置流程,忽略分页变化触发的查询
if (isResetting.value) return;
queryRequest.value.current = currentPage;
queryRequest.value.size = pageSize;
await handleRefresh();
};
setTimeout
/**
* 屏蔽标志(用于阻止程序修改分页参数时引发的不必要查询)
* - 重置时使用
* - 查询前将 current 重置为 1 时使用
*/
const isResetting = ref(false);
/**
* 获取交接分页
*/
const fetchHandoverPage = async () => {
initData();
try {
isMasterLoading.value = true;
// 屏蔽分页变化触发的查询(重置 current 时可能触发 @change)
isResetting.value = true;
queryRequest.value.current = 1;
// 宏任务延迟恢复,确保分页组件的微任务 change 已被拦截
setTimeout(() => {
isResetting.value = false;
}, 0);
const result = await queryHandoverPageForReceive(queryRequest.value);
handovers.value = result.data.rows;
total.value = result.data.total;
} catch (error) {
handovers.value = [];
} finally {
isMasterLoading.value = false;
}
};
/**
* 分页改变
*/
const handlePageChange = async (currentPage: number, pageSize: number) => {
// 若正处于重置流程,忽略分页变化触发的查询
if (isResetting.value) return;
queryRequest.value.current = currentPage;
queryRequest.value.size = pageSize;
await handleRefresh();
};
两种写法在功能上都能达到“在分页组件因 v-model 变化触发 @change 事件期间,让 isResetting 保持为 true”的目的,但它们在实现机制、语义清晰度和与 Vue 生态的融合度上有所区别。
1. 核心区别
| 方式 | 机制 | 时机 |
|---|---|---|
await nextTick() | 等待 Vue 完成 DOM 更新(微任务队列) | 在当前响应式变更引发的 DOM 更新完成后立即恢复,通常早于大多数宏任务 |
setTimeout(..., 0) | 将恢复操作放入宏任务队列 | 在当前调用栈、所有微任务(包括 nextTick)执行完毕后才执行 |
Element Plus 分页组件在 current-page 变化时,内部会通过 watch 触发 change 事件,这个触发过程一般发生在 Vue 的更新周期中,即在 nextTick 的微任务阶段。因此:
-
使用
await nextTick()时,恢复isResetting发生在change事件之后,可以成功拦截。 -
使用
setTimeout(0)时,恢复isResetting发生在更晚的宏任务中,同样能拦截,但多了一层延迟。
2. 哪种更好?
推荐使用 await nextTick(),理由如下:
-
语义直观:
nextTick专为 Vue 设计,明确表达“等待 Vue 完成本轮更新”,而setTimeout是通用 JS 方法,意图不够清晰。 -
性能更优:
nextTick使用微任务,比宏任务setTimeout更快恢复标志,减少不必要的状态滞后。 -
代码风格统一:Vue 项目中通常会优先使用
nextTick处理“DOM 更新后执行”的场景,使用它更符合团队习惯。 -
避免额外延迟:虽然
setTimeout(0)延迟极小,但在高频操作下,多余的宏任务可能影响响应流畅度(微乎其微,但存在)。
3. 最终建议代码
保持您原来的 await nextTick() 写法:
ts
// 屏蔽分页变化触发的查询(重置 current 时可能触发 @change) isResetting.value = true; queryRequest.value.current = 1; // ⏳ 等待分页组件更新完成,确保分页组件的微任务 change 已被拦截 await nextTick(); isResetting.value = false;
确保:
-
外层函数是
async。 -
已从
vue导入nextTick。
这样写清晰、高效,且完全符合 Vue 的响应式机制。

1314

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



