news 2026/7/23 9:23:31

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue.js报错-Maximum-recursive-updates-exceeded

Vue.js 报错:Maximum recursive updates exceeded in component

一句话总结:用「watch + computed + nextTick」三件套,让响应式更新不再无限递归,警告瞬间消失!


正文目录

  1. 报错含义:Vue 在警告什么「递归更新」?
  2. 5 大高频翻车场景 & 修复代码
  3. 万能兜底:watch、computed、nextTick
  4. 预防 checklist(不再踩坑)
  5. 一句话总结

一、报错含义: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 修改了 B,B 变化又触发修改 A,A 又修改 B……死循环了!」

Vue 内置了递归保护机制,当同一个组件的渲染函数被递归触发超过 100 次时,就会抛出此警告并停止更新。

本质:响应式依赖形成了循环引用


二、5 大高频翻车场景 & 修复代码

① watch 修改了被监听的数据 —— 自我递归
<script setup> import { ref, watch } from 'vue'; const count = ref(0); // ❌ watch 修改了被监听的 count,count 变化又触发 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 依赖 firstName,firstName 又依赖 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 依赖 list,watch 修改 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 :modelValue="value" @update:modelValue="handleUpdate" /> </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>

四、预防 checklist

  • watch 回调绝不直接修改被监听的源数据
  • computed只做计算,不产生副作用
  • 响应式数据之间避免互相依赖(A 依赖 B,B 又依赖 A)
  • watch 监听 computed 时,不在回调中修改 computed 的源数据
  • 父子组件 props/emit不做双向转换
  • 控制台「Maximum recursive updates」= 立即检查响应式依赖链是否有环

五、一句话总结

「Maximum recursive updates exceeded」= 响应式依赖形成了循环引用。

用「watch + 条件退出 + computed 只读」三件套,让响应式更新不再无限递归,警告瞬间消失!


最后问候亲爱的朋友们,并邀请你们阅读我的全新著作

📚 《Vue.js 3企业级项目开发实战(微课视频版》

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/23 9:22:46

自学黑客(网络安全入门)

前言&#xff1a;想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01;网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全…

作者头像 李华
网站建设 2026/7/23 9:22:43

爱车开销:你的智能养车好帮手

1. 引言&#xff1a;养车&#xff0c;到底要花多少钱&#xff1f; 买车容易养车难&#xff0c;这几乎是每一位车友的真实心声。加油、保养、保险、停车、洗车、违章罚款……零零碎碎的开销加起来&#xff0c;一年下来真不是一笔小数目。你是否也有过这样的困惑&#xff1a; 每次…

作者头像 李华
网站建设 2026/7/23 9:20:48

实时排名系统技术解析:Redis有序集合与暗票机制实现

SNH48 年度总选进入第 35 天&#xff0c;随着暗票数据的加入&#xff0c;排名格局再次发生显著变化。徐佳琳、李婷、林家谊三位成员成功突破万分大关&#xff0c;而沈馨在昨晚单日斩获 5000 分后&#xff0c;凭借暗票加持直接升至御三家位置&#xff0c;目前综合排名暂列第五。…

作者头像 李华
网站建设 2026/7/23 9:19:20

十、Redis之布隆过滤器

文章目录布隆过滤器是什么&#xff1f;布隆过滤器能干什么&#xff1f;布隆过滤器原理hash冲突布隆过滤器使用添加坑位判断是否存在布隆过滤器使用场景解决缓存穿透的问题&#xff0c;和redis结合bitmap使用黑名单校验&#xff0c;识别垃圾邮件案例布隆过滤器优缺点布隆过滤器是…

作者头像 李华
网站建设 2026/7/23 9:19:03

齐悟同源微囊体究竟是啥东西

1. 齐悟同源微囊体&#xff1a;细胞级健康养护新科技你是否听说过“细胞养护”却不知如何落地&#xff1f;济南百顺健康科技有限公司推出的自体口腔基底粘膜培养液&#xff08;齐悟同源微囊体&#xff09;&#xff0c;正是将细胞科技转化为健康养护的突破性方案。这款直径仅9纳…

作者头像 李华
网站建设 2026/7/23 9:16:22

TI Stellaris LM4F232评估板:从Cortex-M4F到USB OTG与CAN总线的嵌入式开发实战

1. 项目概述 如果你正在寻找一款既能快速上手&#xff0c;又能深入探索ARM Cortex-M4F内核、USB OTG和CAN总线等工业级外设的嵌入式开发平台&#xff0c;那么德州仪器&#xff08;TI&#xff09;的Stellaris LM4F232评估套件绝对是一个绕不开的经典选择。我手头这块板子已经有些…

作者头像 李华