vue3中,nextTick与setTimeout的用法说明

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 的响应式机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值