【发布时间】: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 调用中发送两次(或更多次)。
我已经查看并尝试了以下方法,但均无济于事:
https://www.reddit.com/r/vuejs/comments/7n3zi4/vue_warn_duplicate_keys_detected_vfor_with/
- https://medium.com/@chiatsai/vue-js-common-issue-duplicate-keys-stops-components-rendering-df415f31838e
最后,应该提到的是,我已经尝试过使用/不使用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 快速响应!这适用于我所有的迭代。如果您将此作为答案,我会接受。非常感谢:)