You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 11:54:04