当前位置:   article > 正文

vue - vue使用sort排序时报死循环错误:you may have an infinite update loop in a component render function

you may have an infinite update loop in a component render function.

前言:

在做一个项目的过程中,需要对后端返回的数据做sort()排序处理,然后使用v-for指令渲染页面数据;视图虽然渲染出来了,但是控制台报错如下: You may have an infinite update loop in a component render function(意思是:组件渲染函数中可能有一个无限更新循环)

1,报错的代码如下:

 <div class="list">
      <ul v-for="(item, index) in sortList(copyTextList)" :key="index">
        <li class="item">{{ index + 1 }}{{ item.text }}</li>
      </ul>
    </div>
  export default {
    data() {
    return {
      // 多行文本进行复制
      copyTextList: [],
    };
  },
   mounted() {
    this.initList();
  },
    methods: {
      // 请求数据
    async initList() {
      const { isSuccess, data, code } = await api.requestList.queryCopyList();
      if (isSuccess) {
        this.copyTextList = data;
      }
    },
    // 排序操作
    sortList(list) {
       let sortList = list.sort((a, b) => {
        return a.num - b.num;
      });
      return sortList;
    }
  }

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

运行效果图如下:

在这里插入图片描述

如上代码所示:先在mounted里面请求数据,然后赋值给data里面的copyTextList数组,v-for的时候再对数组进行排序操作;

2,问题分析

问题产生的原因:你在data中定义了一个响应式变量,而这个响应式变量的状态是通过一个函数来返回的,返回的状态结果要显示在Dom中,而这个函数的内部是一个循环;

问题来了:循环没有及时终止,导致变量一直在更新,而Dom又一直在渲染,无限循环,渲染-更新 卡死;

3,解决方案

第一种:

具体问题不一样,但都是死循环类型,所以处理方式也是差不多的。就是不直接对响应式数据进行操作,对响应式数据的副本进行排序然后并返回计算结果;

下面是尤玉溪在github上面给出的解决方案;先使用一个空的slice方法,然后在使用sort排序方法;
不能直接使用sort方法;因为sort方法会改变原数组,从而导致多次渲染;

在这里插入图片描述
而数组的slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。原始数组不会被改变。

所以 上面我的错误代码可以改为:

 // 排序操作
    sortList(list) {
       let sortList = list.slice().sort((a, b) => {
        return a.num - b.num;
      });
      return sortList;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

第二种:

与上面的思路相同;深拷贝一下原数组然后再进行排序:

  // 排序操作
 sortList(list) {
      let sortList =JSON.parse(JSON.stringify(list)).sort((a, b) => {
        return a.num - b.num;
      });
      return sortList;
    },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

第三种:
这一种方法也能解决问题,但是比较麻烦一点:不推荐使用
其实出现报错的根源就在于把数组定义到了 vue实例的data里面,因为vue初始化时会把data里面的所有数据都添加响应式依赖;会监听数组的变化然后做出一些渲染;那我把数据不定义到vue实例里面不就可以了吗;看以下代码改动:

我把copyTextList 定义到了最上面;然后对他赋值然后直接进行sort排序;排完之后再次赋值给一个data里面的newList让它进行渲染视图;

<template>
    <div class="list">
      <ul v-for="(item, index) in newList" :key="index">
        <li class="item">{{ index + 1 }}{{ item.text }}</li>
      </ul>
    </div>
</template>

<script>
import api from '../../api';
// 把数据定义到了外面
let copyTextList = [];
export default {

  data() {
    return {
      newList: [],
    };
  },
  mounted() {
    this.initList();
  },

  methods: {
    // 请求数据
    async initList() {
      const { isSuccess, data, code } = await api.requestList.queryCopyList();
      if (isSuccess) {
        copyTextList = data;
        this.sortList(copyTextList);
      }
    },
    // 排序操作
    sortList(list) {
      this.newList = list.sort((a, b) => {
        return a.num - b.num;
      });
    },
  },
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

End;

如果你们有其他的解决方案;可以写到评论区下面;

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/402359
推荐阅读
相关标签
  

闽ICP备14008679号