Vue的reactivity系统在处理响应式数据更新和异步操作的bug

今天再写vue3+ts项目时,遇到了一个bug

原代码:

<a-col>
      <a-select
        :allowClear="true"
        placeholder="选择学院"
        v-model:value="dto.facultyId"
        @select="search(dto)"
        @deselect="search(dto)"
      >
        <a-select-option v-for="faculty in faculties" :key="faculty.facultyId">
          {{ faculty.facultyName }}
        </a-select-option>
      </a-select>
    </a-col>
    <a-col>
      <a-select
        :allowClear="true"
        placeholder="选择专业"
        v-model:value="dto.programId"
        @select="search(dto)"
        @deselect="search(dto)"
      >
        <a-select-option
          v-for="program in filterPrograms"
          :key="program.programId"
        >
          {{ program.programName }}
        </a-select-option>
      </a-select>
    </a-col>
const filterPrograms = computed<ProgramDto[]>(() => {
  if (dto.value.facultyId === null) return programs.value;
  return programs.value.filter(
    (program) => program.facultyId === dto.value.facultyId
  );
});


watch(
  () => dto.value.facultyId,
  async (newFacultyId) => {
    dto.value.programId = null;
  }
);

使用监听器,当facultyId发生变化时,将paogramId里的值清0,当取消选中facultyId时,@deSelect执行search方法(根据条件分页查询),但是查询时programId仍为原来的值。

原因:由于 Vue 的 reactivity 系统在处理响应式数据更新和异步操作时的执行顺序导致的。虽然 `programId` 被设置为 `null`,但如果在 `watch` 的回调中执行的异步操作并没有等待 `programId` 更新完成,可能会导致发送请求时 `programId` 仍然是原来的值。

解决方法:在重置 `programId` 后明确地等待下一个 DOM 更新循环,再进行请求。这可以通过使用 Vue 的 `nextTick` 来实现,它可以确保所有 DOM 更新完成后再执行下一步操作。
 

更改后代码:

<a-col>
      <a-select
        :allowClear="true"
        placeholder="选择学院"
        v-model:value="dto.facultyId"
      >
        <a-select-option v-for="faculty in faculties" :key="faculty.facultyId">
          {{ faculty.facultyName }}
        </a-select-option>
      </a-select>
    </a-col>
    <a-col>
      <a-select
        :allowClear="true"
        placeholder="选择专业"
        v-model:value="dto.programId"
        @select="search(dto)"
        @deselect="search(dto)"
      >
        <a-select-option
          v-for="program in filterPrograms"
          :key="program.programId"
        >
          {{ program.programName }}
        </a-select-option>
      </a-select>
    </a-col>
watch(
  () => dto.value.facultyId,
  async (newFacultyId) => {
    dto.value.programId = null;
    await nextTick();
    search(dto.value);
  }
);

问题解决。

PS:本人主修后端,前端菜鸡,有不对的地方还请各位大佬指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值