记录uniapp组件报警告Maximum recursive updates exceeded in component <View>

今天写了一个瀑布流报错如下
Maximum recursive updates exceeded in component . This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.

经排查是因为组件中写image一个方法造成的,这就是纯属自己想不开,这里我想写一个计算让图片高度自适应,后来报警告想了一下image mode=“widthFix” 不就是 宽度不变,高度自动变化,保持原图宽高比不变。

错误代码

 <image
  :src="$App.cdnSrc(item?.image)"
   class="item-img"
   :style="{ height: imgHeight + 'rpx' }"
   @load="onImgLoad"
 />

const imgHeight = ref(240);
let onImgLoad = (e) => {
  // 当图片加载完成后,获取图片的原始宽度和高度,并根据宽度计算出高度
  try {
    const { width, height } = e.detail || e.mp.detail;
    imgHeight.value = (height / width) * 100; // 高度 = 原始高度 / 原始宽度 * 100
  } catch (e) {
    //TODO handle the exception
    console.log("onImgLoad", e);
  }
};

正确的

<image
 :src="$App.cdnSrc(item?.image)"
  mode="widthFix"
  class="item-img"
/>
### Vue 中 `Maximum recursive updates exceeded` 错误的原因分析 该错误通常发生在 Vue 的响应式系统中,当某个响应式的副作用(reactive effect)不断修改其自身的依赖项并触发自身重新执行时,就会导致无限递归更新的情况。这种行为可能由组件模板、渲染函数、生命周期钩子(如 `updated`)、或者监听器源函数(watcher source function)引发。 以下是可能导致此问题的具体场景以及解决方案: #### 场景一:组件模板中的逻辑循环 如果在组件模板中存在某种条件判断或表达式计算,而这些表达式又会间接影响到数据模型本身,则可能会造成死循环。例如,在模板中直接调用了某些方法来动态设置状态值[^1]。 **解决办法** 应避免在模板内直接操作可变的数据属性。可以考虑通过 computed 属性返回只读的结果,而不是让视图层直接影响原始数据结构。 ```javascript // 不推荐的方式 computedValue() { this.someDataProperty += 1; return this.someDataProperty * 2; } ``` 改为使用纯函数形式定义计算属性: ```javascript // 推荐方式 computedValue() { const result = this.someDataProperty * 2; console.log(result); // 如果需要调试日志也可以保留 return result; } ``` --- #### 场景二:Watchers 或 Lifecycle Hooks 导致的反馈回路 当 watch 函数监听到了某变量的变化之后再次去更改这个被观察者所对应的值的时候就容易形成闭环效应。比如下面的例子展示了如何因为不当的设计而导致了这样的情况发生[^4]: ```javascript data() { return { duration: '', startTime: '', endTime: '' }; }, methods: { handleDurationChange(newVal) { this.startTime = calculateStartTimeBasedOnDuration(newVal); this.endTime = calculateEndTimeBasedOnDuration(newVal); }, handleStartTimeChange(newVal) { this.duration = recalculateDurationFromStartAndEnd(this.startTime, newVal); this.endTime = adjustEndTimeAccordingToNewStart(newVal); } }, watch: { 'duration'(val) { this.handleDurationChange(val); }, 'startTime'(val) { this.handleStartTimeChange(val); } } ``` 上述代码片段里每次改变任何一个时间参数都会引起其他两个也跟着变动从而陷入无休止的状态切换之中。 **优化建议** 可以通过增加额外标志位控制是否允许进一步传播变更请求;或者是调整业务流程减少不必要的双向绑定关系。 ```javascript let updatingInternally = false; function safeUpdate(fieldToUpdate, newValue){ if(!updatingInternally ){ try{ updatingInternally=true ; fieldToUpdate=newValue ; }finally{ updatingInternally=false ; } } } watch:{ ... } ``` --- #### 场景三:第三方库集成过程中产生的冲突 有时即使我们自己编写的逻辑看似并无明显漏洞仍会出现此类异常提示信息。这可能是由于引入外部插件(像element-plus), 它们内部实现机制复杂度较高加上特定配置选项组合共同作用下才显现出来的现象. 此时应该仔细阅读官方文档确认是否有特殊注意事项需遵循; 同时借助浏览器开发者工具定位具体抛出位置以便更精准地诊断根源所在. --- ### 总结 为了有效预防和处理 “maximum recursive updates exceeded” 这类问题的发生可以从以下几个方面入手: - **审查模板**: 确认是否存在不恰当的操作使得UI层面直接操纵底层model. - **精简Watcher Logic**: 防范多重互斥事件链反应造成的恶性循环. - **利用Debug Tools**: 借助现代IDEs 和 Browsers 提供的强大功能快速锁定可疑区域.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

给钱,谢谢!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值