【问题标题】:Vue.js/Axios - Duplicate results in list. Has unique-keys in v-forVue.js/Axios - 列表中的重复结果。在 v-for 中有唯一键
【发布时间】:2019-09-09 22:42:38
【问题描述】:

我在单独的组件中还有另外两个 v-for 用法。他们有时也会抛出错误。所有三个 v-for 调用都用 v-if/else 包装。以下是产生重复键错误并呈现数据两次的代码:

AccountDashboard.vue

<tbody>
  <tr v-if="!residents.length" class="table-info">
    <td class="text-center">
      <p>
        No residents on record. 
      </p>
    </td>
  </tr>
  <template v-else>
    <tr is="AccountResidentList"
      v-for="resident in residents"
      v-bind:key="'resident-list-' + resident.id"
      v-bind:first_name="resident.first_name"
      v-bind:last_name="resident.last_name"
      v-bind:dob="resident.dob | date_formatted"
      >
    </tr>
  </template>
</tbody>

注意key绑定中的唯一id尝试。

这里看看子组件

ProviderAccountList.vue

<template>
  <tr class="AccountResidentList">
    <td>
      {{ this.$attrs.id }}
    </td>
    <td>
      {{ this.$attrs.first_name }} {{ this.$attrs.last_name }}
    </td>
    <td>
      {{ this.$attrs.dob }}
    </td>
    <td>
      <button @click="toResidentProfile({account_id, id})" class="btn btn-sm btn-purple btn-with-icon">
        <div class="ht-25">
         <span class="icon wd-25"><i class="fa fa-eye"></i></span>
         <span class="pd-x-10">view</span>
       </div>
      </button>
    </td>
    <!--TODO: Add view profile button-->
  </tr>
</template>

 <script>
 import Axios from "axios";
 import router from "../../router";
 import { mapGetters } from "vuex";
 import moment from "moment";

 export default {
  name: "AccountResidentList",
  computed: {
    ...mapGetters['Resident', {
      resident: 'getResident'
    }]
  },
  filters: {
    date_formatted: (date) => {
      return moment(date).format('MMMM Do, YYYY');
    }
  },
  methods: {
    toResidentProfile(account_id, resident_id) {
      router.push(`/accounts/${account_id}/residents/${resident_id}`)
    }
  },
};
 </script>
 <style scoped></style>

我的 Axios 调用如下所示:

Account.js (一个命名空间的 vuex 模块)

  async retrieveAccount(context, account_id) {
      // Axios.defaults.headers.common['Authorization'] = 'Bearer ' + window.$cookies.get('jwt')
      let response
      let valid_id = window.$cookies.get('valid_id');
      response = await Axios.get(`http://localhost:3000/api/v1/providers/${valid_id}/accounts/${account_id}`, { headers: { 'Authorization': 'Bearer ' + window.$cookies.get('jwt') } })
      .then((response) => {
        let account = response.data.locals.account;
        let account_address = response.data.locals.account_address;
        let residents = response.data.locals.residents;
        // set Account
        context.dispatch('Account/setId', account.id, {root: true});
        context.dispatch('Account/setProviderId', account.provider_id, {root: true});
        .
        .
        .

        // set AccountAddress
        // !Array.isArray(array) || !array.length
        if (account.address) {
          context.dispatch('Account/setAddressId', account_address.id, {root: true});
          context.dispatch('Address/setId', account_address.id, {root: true});
        .
        .
        . 

        // set AccountResidents
        // !Array.isArray(array) || !array.length
        residents.forEach(resident => {
          if (resident) {
            // Add object to parent's list
            context.dispatch('Account/setResidents', resident, {root: true});         // Set attr values for object
            context.dispatch('Resident/setId', resident.id, {root: true});
            .
            .
            .
            (remaining attrs removed for brevity)
          }
        })

        router.push(`/providers/${account.provider_id}/accounts/${account_id}`);
      })
      .catch(function(error) {
        console.log(error);
      })

注意:Account 操作#setResidents 只是调用将一个居民添加到列表总数的mutator。

i.e state.list.push(resident)

我记录了对控制台的响应,并且可以确认数据没有从我的 Axios 调用中发送两次(或更多次)。

我已经查看并尝试了以下方法,但均无济于事:

最后,应该提到的是,我已经尝试过使用/不使用template 来包装列表的变体,包括/不包括template 中的for循环等。

没想到迭代一个集合会这么麻烦。

我是否忽略了一些明显的东西?

更新:什么对我有用

我需要访问 resident.id 并且括号中声明的 id 似乎是一个索引。所以这里看看是什么消除了重复的渲染错误,即使在修复了重复的键错误之后也允许我访问居民的 id:

<template v-else>
  <tr is="AccountResidentList"
    v-for="(resident, id) in residents"
    v-bind:key="id"
    v-bind:id="resident.id"
    v-bind:first_name="resident.first_name"
    v-bind:last_name="resident.last_name"
    v-bind:dob="resident.dob | date_formatted"
  >
  </tr>
</template>

再次感谢@Billal Begueradj 的协助!

【问题讨论】:

  • 试试:v-for="(resident, id) in residents" :key="'id"
  • @Billal Begueradj +1 快速响应!这适用于我所有的迭代。如果您将此作为答案,我会接受。非常感谢:)

标签: vuejs2 axios v-for


【解决方案1】:

对我来说,我怀疑在 residents 中存在具有相同 ID 的条目。所以我们必须想办法解决这个问题。我们可以给它一个有效的尝试如下:

<tr 
  is="AccountResidentList"
  v-for="(resident, id) in residents"
  :key="id"
  // rest of your code

【讨论】:

  • 我的重复键错误消失了,但是对于具有相同 id 的条目而言,我的列表现在被渲染了两次。插图(console.log 的图像)显示了每个在场居民的唯一 ID。 ping我的服务器时有什么原因会改变吗?
  • 重复键错误消失了。我的列表一直在重复,直到我允许我的绑定键充当 id。在修复双重渲染之前,我还绑定了 id,导致了 dups。删除它并使用键代替返回所需的结果。
  • 很难遵循 Account.js 中的代码,尤其是没有我可以尝试的可测试代码。但是,请尝试: 1. 在 AccountDashboard.vue 中将 is="AccountResidentList" 替换为 class="AccountResidentList"。 2. ProviderAccountList.vue,删除`` 和&lt;/tr&gt;@sirramongabriel 如果它没有帮助,您可以不接受我的回答,希望其他人可以深入了解您的代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-05
  • 2018-05-15
  • 2017-02-08
  • 2020-10-21
  • 2020-04-06
相关资源
最近更新 更多