对表格进行排序时,Vue v-for循环中的重复键

Posted

技术标签:

【中文标题】对表格进行排序时,Vue v-for循环中的重复键【英文标题】:Duplicate Keys in Vue v-for Loop When Table is Sorted 【发布时间】:2020-06-21 23:12:36 【问题描述】:

我的 Vue 应用程序使用 vuefire 从 Firestore 导入数据。

我从“行”集合中导入数据,如下所示:

firestore() 
  return 
    lines: db.collection("lines")
  

每条记录都有一个 Firestore 生成的 id,然后我在 v-for 循环中使用一个键,例如:

<thead>
  <tr>
    <th>Code</th>
    <th @click="sort_string(lines,'name')"> Name</th>
    <th>Quantity</th>
  </tr>
</thead>
<tbody v-for="line in lines" :key="line.id">
  <tr>
    <td>line.code</td>
    <td>line.name</td>
    <td>line.quantity</td>
    <button @click="pick_one(line)">+1</button>
    ...

有一个方法pick_one直接改变Firestore上的数量:

pick_one(line) 

  const new_quantity = line.quantity + 1;      
  db
    .collection("lines")
    .doc(line.id)
    .update( quantity: new_quantity );

所有这些都可以正常工作直到sort()底层数组('lines')。

如果我对表进行排序,然后调用函数pick_one,我会收到重复键错误:

[Vue warn]: Duplicate keys detected: 'RaTIINFWTQxHQPyRmfsQ'. This may cause an update error.

我只能假设这与 Vuefire 处理 update() 调用的方式有关,因为排序数组的行为不会导致这个问题,只是在排序时更新数组中的一行。

我的排序函数(vue方法)是这样的:

sort_string(table, column) 
  console.log("sorting")
  this.sort_toggle = -this.sort_toggle;

  return table.sort((a, b) => 
    if (
      a[column].toString().toUpperCase() <
      b[column].toString().toUpperCase()
    ) 
      return -this.sort_toggle;
    
    if (
      a[column].toString().toUpperCase() >
      b[column].toString().toUpperCase()
    ) 
      return this.sort_toggle;
    
    return 0;
  );
,

有没有办法避免这种行为?

【问题讨论】:

你能展示做排序的方法吗?并检查 Vuefire 在更新后是否返回相同的 id 我已更新问题以包含排序功能 你怎么打电话给sort_string?那是方法还是计算属性?这可能与 Array.prototype.sort() 改变原始数组有关 在列标题中按上面编辑的问题排序:&lt;th @click="sort_string(lines,'name')"&gt; Name&lt;/th&gt; 【参考方案1】:

Phil 的评论为这种行为提供了线索——sort() 函数正在处理基础数据而不是副本。

我已经修改了我的模板,以便 v-for now 循环遍历一个计算数组,该数组可以使用(稍微修改的)函数进行排序。

排序函数现在使用slice() 创建底层数组的副本:

computed: 
  sorted_lines() 
    return sort_string(lines, this.sort_column) // name of the column/filed to sort by
  

sort_string 函数现在看起来像这样(添加了slice()

sort_string(table, column) 
  console.log("sorting")
  //this.sort_toggle = -this.sort_toggle; // moved elsewhere

  return table.slice().sort((a, b) =>  // slice() then sort()
  if (
    a[column].toString().toUpperCase() <
    b[column].toString().toUpperCase()
  ) 
    return -this.sort_toggle;
  
  if (
    a[column].toString().toUpperCase() >
    b[column].toString().toUpperCase()
  ) 
    return this.sort_toggle;
  
  return 0;
);
,

【讨论】:

以上是关于对表格进行排序时,Vue v-for循环中的重复键的主要内容,如果未能解决你的问题,请参考以下文章

无法在 vue.js 中的“v-for”(数据不可迭代)中对数据进行排序

Vue.js - 如何按特定属性对数组中的对象进行排序并使用“v-for”进行渲染

Vue - ElementUI中循环渲染表格,控制字段的显示与隐藏 v-if与v-for同时使用

vuejs中的v-for怎样动态增加循环数据

来自对象键和嵌套数组的 Vue.js v-for 循环

第十节:Vue指令:v-for列表循环