Vue3使用watch监听datepicker的modelValue和range出现递归更新报错及延迟问题
问题根因
你的代码中两个watcher形成了无限触发的循环链路,是警告和延迟的直接原因:
- 内部
range值变化 → 触发第一个watcher → 发送update:modelValue事件 → 父组件更新传入的modelValue属性 - 第二个watcher监听
props.modelValue变化 → 修改内部range.value→ 再次触发第一个watcher,循环往复直到Vue触达更新上限抛出警告,响应延迟是循环占用渲染线程导致的。
解决方案
方案1:新增值比对逻辑,阻断无意义更新(改动最小)
在两个watcher中先比对新值和旧值是否完全一致,只有值真实变化时才执行后续操作:
watch(range, (newRange) => { // 和当前props.modelValue比对,值一致则跳过emit if (newRange.start === props.modelValue.start && newRange.end === props.modelValue.end) return emit("update:modelValue", newRange); }); watch(() => props.modelValue, (newModelVal) => { // 和当前range比对,值一致则跳过修改 if (newModelVal.start === range.value.start && newModelVal.end === range.value.end) return range.value = { start: newModelVal.start, end: newModelVal.end, }; } );
方案2:使用带get/set的计算属性替代双watcher(更符合Vue最佳实践)
直接将range定义为计算属性,天然避免循环触发问题,代码更简洁:
const range = computed({ get() { return { start: props.modelValue.start, end: props.modelValue.end } }, set(newVal) { emit('update:modelValue', newVal) } })
方案3:Vue3.4+版本可使用defineModel宏进一步简化
如果项目使用Vue3.4及以上版本,无需手动声明props和emit,用defineModel即可快速实现双向绑定:
// 声明双向绑定变量,自动对应modelValue prop和update:modelValue事件 const model = defineModel() const range = computed({ get() { return { start: model.value.start, end: model.value.end } }, set(newVal) { model.value = newVal } })
内容的提问来源于stack exchange,提问作者slappy
相关产品推荐
相关产品推荐

