今天再写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:本人主修后端,前端菜鸡,有不对的地方还请各位大佬指正