Vue.js报错-Maximum-recursive-updates-exceeded

发布时间:2026/7/23 9:23:43
Vue.js报错-Maximum-recursive-updates-exceeded Vue.js 报错Maximum recursive updates exceeded in component一句话总结用「watch computed nextTick」三件套让响应式更新不再无限递归警告瞬间消失正文目录报错含义Vue 在警告什么「递归更新」5 大高频翻车场景 修复代码万能兜底watch、computed、nextTick预防 checklist不再踩坑一句话总结一、报错含义Vue 在警告什么「递归更新」当你在控制台看到Maximum recursive updates exceeded in component xxx. This means you have a reactive effect that is mutating its own dependency and recursively triggering itself.Vue 在告诉你「你的响应式逻辑形成了无限循环 —— A 修改了 BB 变化又触发修改 AA 又修改 B……死循环了」Vue 内置了递归保护机制当同一个组件的渲染函数被递归触发超过 100 次时就会抛出此警告并停止更新。本质响应式依赖形成了循环引用。二、5 大高频翻车场景 修复代码① watch 修改了被监听的数据 —— 自我递归script setup import { ref, watch } from vue; const count ref(0); // ❌ watch 修改了被监听的 countcount 变化又触发 watch watch(count, (newVal) { count.value newVal 1; // ❌ 死循环 }); /script修复用中间变量或条件退出script setup import { ref, watch } from vue; const count ref(0); // ✅ 加退出条件避免无限递归 watch(count, (newVal) { if (newVal 10) return; // ✅ 有上限 count.value newVal 1; }); /script② computed 里修改了依赖的响应式数据script setup import { ref, computed } from vue; const price ref(100); const count ref(2); // ❌ computed 中修改了依赖的 price const total computed(() { price.value price.value 10; // ❌ 修改依赖 → 死循环 return price.value * count.value; }); /script修复computed 只读不修改依赖script setup import { ref, computed } from vue; const price ref(100); const count ref(2); // ✅ computed 只做计算不修改依赖 const total computed(() price.value * count.value); // ✅ 需要修改 price用 watch 或事件 function updatePrice() { price.value 10; } /script③ 模板中绑定了互相依赖的数据script setup import { ref, computed } from vue; const firstName ref(张); const lastName ref(三); // ❌ fullName 依赖 firstNamefirstName 又依赖 fullName const fullName computed(() { firstName.value fullName.value; // ❌ 互相依赖 return firstName.value lastName.value; }); /script修复单向数据流避免互相依赖script setup import { ref, computed } from vue; const firstName ref(张); const lastName ref(三); // ✅ 单向依赖fullName 依赖 firstName但 firstName 不依赖 fullName const fullName computed(() firstName.value lastName.value); // ✅ 需要反向更新用 watch watch(fullName, (val) { // 单独处理 }); /script④ watch 监听 computed又在回调中修改 computed 的源数据script setup import { ref, computed, watch } from vue; const list ref([1, 2, 3]); // ❌ doubleList 依赖 listwatch 修改 list → doubleList 变化 → watch 触发 const doubleList computed(() list.value.map(i i * 2)); watch(doubleList, () { list.value.push(list.value.length 1); // ❌ 修改源数据 → 死循环 }); /script修复监听不同数据源或用 once 标志script setup import { ref, computed, watch } from vue; const list ref([1, 2, 3]); const doubleList computed(() list.value.map(i i * 2)); // ✅ 监听 doubleList 的长度而非内容或加条件 watch(() doubleList.value.length, (newLen, oldLen) { if (newLen oldLen) return; // ✅ 避免无意义触发 // 只在真正需要时更新 }); /script⑤ 组件 props 和 emit 形成循环!-- 父组件 -- script setup import { ref } from vue; import Child from ./Child.vue; const value ref(); const handleUpdate (val) { value.value val.toUpperCase(); // ❌ 转换后又传给子组件 → 子组件 emit → 再传回 }; /script template Child :modelValuevalue update:modelValuehandleUpdate / /template!-- 子组件 -- script setup const props defineProps([modelValue]); const emit defineEmits([update:modelValue]); // ❌ watch props 变化后立即 emit父组件又修改 → 循环 watch(() props.modelValue, (val) { emit(update:modelValue, val.toLowerCase()); // ❌ 死循环 }); /script修复子组件不做反向转换或用 computed 只读!-- 子组件修复版 -- script setup import { computed } from vue; const props defineProps([modelValue]); const emit defineEmits([update:modelValue]); // ✅ 用 computed 展示转换后的值不 emit 回去 const displayValue computed(() props.modelValue.toLowerCase()); // ✅ 只在用户输入时 emit function handleInput(e) { emit(update:modelValue, e.target.value); } /script三、万能兜底watch、computed、nextTick场景工具示例需要修改被监听的数据watch 条件退出if (val 10) return;需要派生数据computed只读computed(() a b)需要延迟更新nextTicknextTick(() { ... })需要批量更新watch flush:‘post’watch(src, fn, { flush: post })万能模板script setup import { ref, watch, nextTick } from vue; const data ref(null); // ✅ 万能模板条件退出 nextTick 延迟 watch(data, async (newVal) { if (!newVal) return; // ✅ 条件退出 await nextTick(); // ✅ 延迟到 DOM 更新后 // 安全地修改数据 }); /script四、预防 checklistwatch 回调绝不直接修改被监听的源数据computed只做计算不产生副作用响应式数据之间避免互相依赖A 依赖 BB 又依赖 Awatch 监听 computed 时不在回调中修改 computed 的源数据父子组件 props/emit不做双向转换控制台「Maximum recursive updates」 立即检查响应式依赖链是否有环五、一句话总结「Maximum recursive updates exceeded」 响应式依赖形成了循环引用。用「watch 条件退出 computed 只读」三件套让响应式更新不再无限递归警告瞬间消失最后问候亲爱的朋友们并邀请你们阅读我的全新著作 《Vue.js 3企业级项目开发实战微课视频版》