Vue中v-for循环内调用函数引发无限循环的解决方法
Vue v-for循环内执行函数避免无限递归渲染
问题场景
想在Vue模板的v-for循环内执行函数(无需触发事件或渲染数据),比如递增numberOfItems统计循环次数,但调用addNumberOfItems()后出现无限递归渲染,控制台警告:
Maximum recursive updates exceeded. 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.
组件代码:
<template> <div class="repeater-wrapper"> <div class="repeater-item" v-for="(input, index) in min" > {{ addNumberOfItems() }} {{ sayHello() }} </div> </div> </template> <script> export default { props: { min: { type: Number }, max: { type: Number, default: 10 } }, data() { return { status: 'normal', validate: true, numberOfItems: 0 } }, methods:{ addNumberOfItems(number=1){ console.log( 'It is fired', this.numberOfItems ) this.numberOfItems += number; return this.numberOfItems; }, sayHello(){ //Any other function I want to execute on each loop } } } </script>
父组件调用:
<Repeater :min="2"/>
问题原因
模板中调用addNumberOfItems()时修改了响应式数据numberOfItems,触发组件重新渲染;重新渲染时模板会再次调用该函数,再次修改数据,形成无限递归循环。
解决方案
1. 避免在模板中修改响应式数据
统计循环次数不需要在循环内递增,直接通过props.min或计算属性获取:
<script> export default { // ...其他代码 computed: { itemCount() { // 直接返回循环次数,无需修改响应式数据 return this.min; } } } </script>
如果需要将次数存入numberOfItems,在钩子函数或watch中赋值:
<script> export default { // ...其他代码 mounted() { // 组件挂载后初始化次数 this.numberOfItems = this.min; }, watch: { // 监听min变化,更新次数 min(newVal) { this.numberOfItems = newVal; } } } </script>
2. 执行无副作用函数的正确方式
如果要执行sayHello()这类不修改响应式数据的函数,有两种方式:
- 直接在模板中调用(确保函数无副作用,不会触发重渲染):
<template> <div class="repeater-item" v-for="(input, index) in min" :key="index"> {{ sayHello(index) }} </div> </template>
- 在钩子函数中遍历执行(适合需要批量处理的场景):
<script> export default { // ...其他代码 mounted() { for (let i = 0; i < this.min; i++) { this.sayHello(i); } }, watch: { min(newVal) { // 当min变化时重新执行 for (let i = 0; i < newVal; i++) { this.sayHello(i); } } }, methods: { sayHello(index) { console.log(`处理第${index}个循环项`); // 仅执行无副作用操作 } } } </script>
3. 核心原则
模板只负责渲染数据,所有修改响应式数据的操作必须放在钩子函数、事件处理器或watch中,避免触发无限递归渲染。
内容的提问来源于stack exchange,提问作者Dani Pardo
相关产品推荐
相关产品推荐

