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


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

    这个问题很奇怪,之前从来没有遇到过。如果是我自己主导的项目,倒也好办,慢慢 debug 就是;偏偏在公司的项目里遇到这个问题,而公司项目的体系结构很复杂,我还没完全掌握。更恼火的是,因为体系复杂,debug 也非常困难,再加上尚无测试框架,这个难搞啊……

    好死不死的,当时是下午3、4点钟,正好到了肚饿的时刻,结果又落入低血糖状态,真是屋漏偏逢连阴雨,船小又碰顶头风,饿得我脑仁生疼……

    不过终于还是被我 Google + debug 出来。事实上是这样的,在 v-for 循环当中,如果用方法或者计算属性对 vm.$data 的属性进行操作,理论上,可能因为修改到循环对象,诱发无限循环。此时 Vue 就会发出警告(并不是真的已经无限循环了)。

    例如这样一个组件,它里面是用 :checked + <label> 实现的一组按钮。它有以下功能:

    1. 为了能够分组,需要设置它们的 name 属性
    2. 为了能够用 <label> 控制 <input>,需要给 <input> 设置 id
    3. 按钮可以被删除

    于是我选择这样做:

    <template>
    <div>
      <template v-for="(item, index) in items">
        <input type="checkbox" :name="'my-component-' + selfIndex" :id="getID">
        <label :for="getID(false)">
        <button type="button" @click="remove(index)">&times;</button>
      </template>
    </div>
    </template>
    
    <script>
    let count = 0;
    
    export default {
      data() {
        return {
          selfIndex: 0,
          itemIndex: 0,
        }
      },
      methods: {
        getID(increase = true) { // 注意,问题就出在这里
          if (increase) {
            this.itemIndex++;
          }
          return `my-component-${this.selfIndex}-${this.itemIndex}`;
        },
      },
      beforeMount() {
        this.selfIndex = count;
        count++;
      }
    }
    </script>

    这里,为了能生成唯一 ID,我选择每次循环都对 vm.itemIndex++,这就会出现前面说的问题,存在隐患。

    解决的方案有两种,一种是把 itemIndex 也放在局部变量里,使它不直接关联在组件上;另一种则是写一个全局的唯一 ID 生成函数,然后引用进来。原理都是一样的。重复的部分就不写了,修改后大体如下:

    方案一

    <script>
    let count = 0;
    let itemCount = 0; // 把元素计数器放在这里
    
    export default {
      methods: {
        getID(increase = true) {
          if (increase) {
            itemCount++;
          }
          return `my-component-${this.selfIndex}-${itemCount}`;
        }
      }
    };
    </script>

    方案二

    // helper.js 生成唯一 id
    let count = 0;
    export default function uniqueID(increase = true) {
      if (increase) {
        count++;
      }
      return `prefix-${count}`;
    }
    
    // 原来的组件
    import uniqueID from './helper';
    
    export default {
      methods: {
        getID(increase = true) {
          let id = uniqueID(increase);
          return `my-component-${this.selfIndex}-${id}`;
        }
      }
    }

    【广告】肉老师的面试题详解

    顺便做个广告,我的新讲堂已经上线,将于下周二直播。

    这次我决定把自己积累的面试题详细地介绍给所有来听课的同学。从设置这道题的目的,考察的方向,希望听到的答案,答出多少大约是什么评价等等都来个彻底的公开。相信大家听后,可以更加明确日常学习的方向。

    目前还在75折销售中,欢迎大家,链接在此


  • 相关阅读:
    Ignoring HTTPS certificates
    利用Httponly提升web应用程序安全性
    HttpUrlConnection java.net.SocketException: Software caused connection abort: recv failed
    DISPOSE_ON_CLOSE 和 EXIT_ON_CLOSE 的区别
    Swing多线程
    攒机知识积累
    数组最大子数组和
    fork()详解
    理解Socket编程【转载】
    STM32F407_LED代码
  • 原文地址:https://www.cnblogs.com/vicky-li/p/11610936.html
Copyright © 2020-2023  润新知