[vue]You may have an infinite update loop in a component render function

996 阅读2分钟

 最近在写代码的时候遇到一个问题。

 场景是父组件引用了子组件,并给子组件传递了一个对象,该对象由父组件中的A方法构造并return。 在父组件的data 中定义了一个变量,在A方法中执行自增。

页面刷新后发现控制台报错:You may have an infinite update loop in a component render function。 代码如下:

父组件:

<template>  <div>    <h2>杭州西站</h2>    <childCpt :params="getObj()"></childCpt>  </div></template><script>import childCpt from "@/views/ChildCpt/src/ChildCpt.vue";export default {  components: { childCpt },  data() {    return {      num:0    };  },  methods: {    getObj() {      //自增      this.num++;      let params = {};      params.id = "eeee";      return params;    },  },  // 以下为测试内容  // mounted() {  //   console.log("rerender")  // },  // beforeUpdate(){  //   console.log("rerender1")   //  },  // updated(){  //  console.log("rerender2")  // } };</script>

子组件:

<template>  <div>    <h2>{{ params.id }}</h2>  </div></template><script>export default {  props: ["params"],  data() {    return {};  },};</script>

贴一下测试内容中的打印信息和报错内容

贴不上来图,还是在代码块里展示以上信息....

rerender     //打印信息
<101>rerender1  //打印信息

[Vue warn]: You may have an infinite update loop in a component render function.

found in...    //报错信息

<102> rerender2  //打印信息

以上,mounted中的打印操作执行了一次,但是beforeUpdate和updated一直不断地在执行,直到报错。

有两个问题:

1. 为什么mounted函数被调用了一次,beforeUpdate和updated却不断被调用?

2. 为什么beforeUpdate和updated会不断被调用,形成无限循环?

问题原因:

num为初始值即0 的时候,进行了一次渲染,完成了节点挂载。

这个过程中,调用了一次mounted,触发了 num的第一次自增,同时data也变化一次。watcher观测到data 的变化,就去调用了beforeUpdate,做虚拟节点更新准备(比如剔除重复的无意义更新)。准备结束后,进入更新阶段 ,源码: vm._update(vm._render(), hydrating)

这个过程中,调用了updated函数,去进行本次页面更新(未真正完成页面本次更新,即真实视图上没有发生变化),在这期间又触发了getObj()的执行,num 再增长一次,data 改变=>beforeUpdate=>updated=>getObj()=>num 增长,闭环,形成无限循环。

ps: 如果页面有自增数字显示之类的需求,可用computed来实现。以下为demo:

<template>  <div>    <h3>{{numadd}}</h3>  </div></template><script>export default {  data() {    return {      num:0    };  },  computed:{    numadd:function(){      setTimeout(()=>{       this.num++      },3000)      return this.num    }  }};</script>