【问题标题】:You may have an infinite update loop in a component render function您可能在组件渲染函数中有无限更新循环
【发布时间】:2017-08-26 08:24:19
【问题描述】:

我是 VueJS 的新手,我收到了来自 Vue 的警告,

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

当我在 V-bind:style 中使用 V-for 变量时,这是一个示例: 在模板中:

<div v-for="item in model.items" v-bind:class="test(item.result)">
{{item.id}}
</div>

在脚本中:

data() {
    return {
        accept: false,
        not_accept: false,
    };
},
methods: {
    test(result) {
        if (result == 'accept') {
            this.accept = true;
            this.not_accept = false;
        } else if (result == 'Not accept') {
            this.accept = false;
            this.not_accept = true;
        } else {
            console.log(result);
        }

        return {
            success: this.accept,
            danger: this.not_accept,
        };
    },
},

【问题讨论】:

    标签: node.js vue.js vuejs2


    【解决方案1】:

    @Decade 对这个问题的看法是正确的。这是确切的问题:

    1. 您正在使用某个状态值渲染项目列表的 render 方法

    注意:只要状态发生变化,就会触发渲染方法

    1. 然后您尝试根据函数test 的结果绑定类,此函数存在缺陷,因为它再次尝试改变状态,从而导致渲染-测试-渲染循环。

    你可以通过让你的测试函数不改变状态来解决这个问题,就像这样:

    methods: {
        test(result) {
            let accept;
            if (result == 'accept') {
                accept = true;
            } else if (result == 'Not accept') {
                accept = false;
            } else {
                console.log(result);
            }
    
            return {
                success: accept,
                danger: !accept,
            };
        },
    }
    

    希望对你有所帮助!

    【讨论】:

    • 计算属性不能被调用,因此不能有参数。它们像属性一样被访问,所以这段代码不起作用。
    • @LinusBorg 感谢您发现错误,我不知道。我修复了这个例子。
    • 在我的例子中,我将一个对象从状态值传递给一个新变量。我为解决这个问题所做的是使用扩展运算符,如下所示:``` let obj = {}; // 一些条件 obj = {...objFromState} ```
    • 只是添加 - 在 vuejs 下,您可以执行与上面类似的操作,不需要 let 或 var 来声明变量 - 一个警告 - 如果您尝试在循环中分配它 - 作为示例收音机按钮当前对象成为最后一行 - 我删除了 :&lt;span style="display:none;"&gt; &lt;!-- this sets currentObject locally to be current stored results --&gt; {{ currentObject = ( findFromArray(stored[0].facilities,'id',currentField.id).currentObject )}} &lt;/span&gt; 并调用 findFromArray(stored[0].facilities,'id',currentField.id).currentObject ) 而不是变量名 - 一切正常
    • 所以基本上操作的错误是在方法中不断更改数据变量,因此 vue.js 不断更新渲染。我现在在导出对象之外创建了一个 let 变量,并根据我的需要对其进行了修改。感谢您的提示,现在更清楚了。
    【解决方案2】:

    首先,我不知道为什么你有not_accept,你不能用!this.accept 代替它吗?

    我不是 100% 确定您为什么会收到此警告,但我的想法是这样的。

    v-bind:class 的观察者正在观察 item.resultthis.acceptthis.not_accept 的变化。这些值的任何更改都将导致通过再次调用test 重新呈现它。但是在test中,你正在修改this.acceptthis.not_accept,所以Vue需要再次重新检查结果是否因此而改变,这样做可能会改变this.acceptthis.not_accept em>再次,以此类推。

    class 绑定和数据有缺陷。每个项目的class 将被设置为相同的东西,但看起来好像您想要根据item.result 为每个项目自定义样式。你真的不应该在test 中修改this 的任何属性。

    很难给出一个全面的答案,因为我不完全确定你的组件是如何工作的以及它应该做什么。

    【讨论】:

      【解决方案3】:

      如果你调用一个函数而不是在 vue 指令中传递一个函数,你会得到这个错误。这是一个例子:

      我自定义了directive to load data via AJAX when a boostrap tab is displayed

      这很糟糕:

       v-on-show-bs-tab="getFirstPageSites()"
      

      在这里,vue 似乎调用了函数(或者更确切地说评估表达式)并将结果传递给指令。

      这很好:

       v-on-show-bs-tab="getFirstPageSites"
      

      这里我通过名称传递函数,以便我可以在指令中调用它。

      【讨论】:

      • 并不真正适用于 OP 的问题。您如何将当前项目数据传递给函数?
      • @Mike 我通过搜索错误消息在 Google 上找到了这个问题。这就是为什么我收到错误消息和对我有用的修复程序。
      【解决方案4】:

      我不小心做了类似的事情,而且用未经训练的眼睛不容易发现:在过滤器中的数组上调用.sort()sort 改变数组,从而使组件重新渲染。解决方法是先slice数组并创建一个浅拷贝,然后排序。

      不好:

       filters: {
          sortedDays(days) {
            return days.sort().join(', ');
          },
        },
      

      好:

       filters: {
          sortedDays(days) {
            return days.slice().sort().join(', ');
          },
        },
      

      【讨论】:

      • 我认为这很好是犯了这个错误,但性能明智然后更快的方法是[...days].join(', ');
      • 如果您比较两者,您会忘记那里有一个sort。他们很接近,但首先要买一点:measurethat.net/Benchmarks/Show/14783/0/…
      【解决方案5】:

      在组件中使用:click 而不是@click 时犯了同样的错误

      【讨论】:

        【解决方案6】:

        我做错了什么:

        我在使用数据时没有使用箭头函数

        例如:

        data() {
          state: {
             foo: 'bar'
          }
        },
        created() {
          bus.$on('data_change', function(data) {
            this.state = Object.assign({}, this.state, data); <-- this will cause an infinite loop
          });
        }
        

        改用箭头函数:

        created() {
          bus.$on('data_change',(data) => {
            this.state = Object.assign({}, this.state, data);
          });
        }
        

        认为这看起来像是一个常见的错误

        【讨论】:

          【解决方案7】:

          在我的例子中,我在一个函数中改变一个对象,我认为每当我改变它时,它会一次又一次地调用同一个函数(一种递归)。所以不要在函数体中有这个:

          this.someProperty = myObject;
          

          我将所有代码放入一个返回“myObject”的新函数(函数名称为totalesSimples)中。

          在 HTML 部分,而不是像这样显示:

          {{someProperty}}
          

          我展示了它:

          {{totalesSimples()}}
          

          这样,我并没有改变函数内部的属性并显示它;我正在显示函数的结果。

          【讨论】:

            猜你喜欢
            • 2019-02-07
            • 1970-01-01
            • 2019-02-12
            • 2020-06-03
            • 2021-04-30
            • 2020-07-04
            • 2021-05-05
            • 2019-10-11
            • 2017-10-19
            相关资源
            最近更新 更多