首页 > 解决方案 > NonErrorEmittedError:用 v-for 渲染的组件列表应该有明确的键

问题描述

运行gulp --ship终端时显示以下错误:

NonErrorEmittedError: (Emitted value instead of an instance of Error) <app-Player-List v-for="player in players">: component lists rendered with v-for should have explicit keys. See https://vuejs.org/guide/list.html#key for more info.

我有一TeamInfos.vue堂课,当我在 Visual Studio 中打开它时,它会将一行标记为红色:

<app-Player-List v-for="(player, index) in players" :player="player" :index="index++"></app-Player-List>

当我将光标移到它上面时,它会告诉我

[vue/valid-v-for]
Custom elements in iteration require 'v-bind:key' directives.eslint-plugin-vue

我不知道如何修复这个错误。这是整个班级

<template>
  <div>
    <div class="row" style="margin-bottom:20px">
      <button class="btn btn-primary" @click="changeSelectedComp">Back</button>
    </div>
    <h2 style="margin-bottom:10px;">{{this.$store.state.selectedTeam.TeamName }}</h2>
    <div class="row" style="margin-bottom:10px">
      <div class="d-inline col-lg-3 col-md-3 col-sm-6" padding="0px">
        <b>Coach</b>
      </div>
      <div class="d-inline col-lg-3 col-md-3 col-sm-6" padding="0px">{{ this.team[0].Coach }}</div>
      <div class="d-inline col-lg-3 col-md-3 col-sm-6" padding="0px">
        <b>Coach Asst.</b>
      </div>
      <div
        class="d-inline col-lg-3 col-md-3 col-sm-6"
        padding="0px"
      >{{ this.team[0].CoachAssistant }}</div>
    </div>
    <div class="row" style="margin-bottom:10px">
      <div class="d-inline col-lg-3 col-md-3 col-sm-6" padding="0px">
        <b>Coach Tel.</b>
      </div>
      <div class="d-inline col-lg-3 col-md-3 col-sm-6" padding="0px">{{ this.team[0].CoachTel }}</div>
      <div class="d-inline col-lg-3 col-md-3 col-sm-6" padding="0px">
        <b>Coach Asst. Tel.</b>
      </div>
      <div
        class="d-inline col-lg-3 col-md-3 col-sm-6"
        padding="0px"
      >{{ this.team[0].CoachAssistTel }}</div>
    </div>

    <div class="row">
      <div class="d-inline col-lg-3 col-md-3 col-sm-6" padding="0px">
        <b>Coach Addr.</b>
      </div>
      <div class="d-inline col-lg-3 col-md-3 col-sm-6" padding="0px">{{ this.team[0].CoachAddress }}</div>
      <div class="d-inline col-lg-3 col-md-3 col-sm-6" padding="0px">
        <b>Coach Asst. addr.</b>
      </div>
      <div
        class="d-inline col-lg-3 col-md-3 col-sm-6"
        padding="0px"
      >{{ this.team[0].CoachAssistAddress }}</div>
    </div>
    <div class="row" style="margin-bottom:10px">
      <div class="d-inline col-lg-3 col-md-3 col-sm-6">
        <b>Comments</b>
      </div>
      <div class="d-inline col-lg-6 col-md-6 col-sm-6" padding="0px" >{{ this.team[0].Comments }}</div>
    </div>

    <table class="table table-hover">
      <thead>
        <tr>
          <th scope="col" class="text-center">#</th>
          <th scope="col" class="text-center">Player</th>
          <th scope="col" class="text-center">Position</th>
          <th scope="col" class="text-center">Birthday</th>
          <th scope="col" class="text-center">Nationality</th>
          <th scope="col" class="text-center">Phone</th>
        </tr>
      </thead>
      <tbody>
        <app-Player-List v-for="(player, index) in players" :player="player" :index="index++"></app-Player-List>
      </tbody>
    </table>
  </div>
</template>

<script>
import * as $ from "jquery";
import PlayerList from "./PlayerList.vue";
export default {
  components: {
    appPlayerList: PlayerList
  },
  data: function() {
    return {
      team: [],
      players: []
    };
  },
  created: function() {
    this.loadTeam();
    this.loadPlayers();
  },
  methods: {
    loadTeam: function() {
      var teamID = this.$store.state.selectedTeam.id;
      var baseUrl = this.$store.state.baseUrl;
      var listName = "Team";
      var select =
        "$select=id,TeamName,Coach,CoachTel,CoachAddress,CoachAssistant,CoachAssistTel,CoachAssistAddress,Comment,TeamName/TeamName";
      var expand = "&$expand=TeamName";
      var filter = "&$filter=ID eq '" + teamID + "'";
      // var filter = "&$filter=PlayerNameId eq '" + playerID + "'";
      baseUrl +=
        "GetByTitle('" + listName + "')/items?" + select + expand + filter;
      var $this = this;
      $.ajax({
        url: baseUrl,
        type: "GET",
        headers: {
          Accept: "application/json;odata=verbose"
        },
        async: false,
        success: function(data, textStatus, xhr) {
          $this.teamData(data.d.results);
        },
        error: function(xhr, textStatus, errorThrown) {
          alert("error:" + JSON.stringify(xhr));
          $("#start" + "records").html(" [0]");
        }
      });
    },
    teamData: function(data) {
      this.team = [];
      var $this = this;
      for (var i = 0; i < data.length; i++) {
        $this.team.push({
          id: data[i].ID,
          TeamName: data[i].TeamName.TeamName,
          Coach: data[i].Coach,
          CoachTel: data[i].CoachTel,
          CoachAddress: data[i].CoachAddress,
          CoachAssistant: data[i].CoachAssistant,
          CoachAssistTel: data[i].CoachAssistTel,
          CoachAssistAddress: data[i].CoachAssistAddress,
          Comments: data[i].Comment
        });
      }
    },
    loadPlayers: function() {
      var teamID = this.$store.state.selectedTeam.id;
      //var baseUrl = "/DEV/BBUlm" + "/_api/web/lists/";
      var baseUrl = this.$store.state.baseUrl;
      var listName = "Player";
      var select =
        "$select=id,Name,TeamNameId,IDinformation,Nationality,Telephone,Email,Birthday,Position,Address,Bild,Name";
     // var expand = "&$expand=Name";
      var filter = "&$filter=TeamNameId eq '" + teamID + "'";
      baseUrl +=
        "GetByTitle('" + listName + "')/items?" + select + filter; //+ select;
      var $this = this;
      $.ajax({
        url: baseUrl,
        type: "GET",
        headers: {
          Accept: "application/json;odata=verbose"
        },
        async: false,
        success: function(data) {
          //alert("success");
          $this.playersData(data.d.results);
        },
        error: function(xhr) {
          alert("error:" + JSON.stringify(xhr));
          $("#start" + "records").html(" [0]");
        }
      });
    }, 
    playersData: function(data) {
      this.players = [];
      var $this = this;
      for (var i = 0; i < data.length; i++) {
        var Birthday = this.getJSONDateAsString(data[i].Birthday, "dd.MM.yyyy");
        $this.players.push({
          ID: data[i].ID,
          PlayerID: data[i].NameId,
          Name: data[i].Name,
          IDinformation: data[i].IDinformation,
          Nationality: data[i].Nationality,
          Telephone: data[i].Telephone,
          Email: data[i].Email,
          Birthday: Birthday,
          Position: data[i].Position,
          Address: data[i].Address,
          Picture: data[i].Bild.Url,
          Birthday: Birthday
        });
      } 
    },
    changeSelectedComp: function() {
      this.$store.state.selectedComp = "appTeams";
    },
    getJSONDateAsString: function(jsdatevalue, returnFormat) {
      if ((jsdatevalue == "") | (jsdatevalue == null)) {
        return "";
      }
      return new Date(jsdatevalue).toString(returnFormat);
    }
  }
};
</script>


<style>
</style>

标签: javascriptvue.jsgulpdirective

解决方案


指令创建的每个元素都v-for需要由key属性标识。此属性应使用您迭代的变量之一来定义。像这样 :

<app-Player-List v-for="(player, index) in players" :player="player" :key="'player-list-'+index" :index="index++"></app-Player-List>

这会将 key player-list-0,player-list-1等添加到每个app-Player-List创建的。

此外,您不需要手动迭代index,它v-for会自行完成。如果有的话,您可能会通过迭代:index="index++". 所以你可能应该删除它。相同:player="player",你不需要那个。

也许尝试:

<app-Player-List v-for="(player, index) in players" :key="'player-list-'+index"></app-Player-List>

最后一件事,我不知道你到底想做什么,但你v-forapp-Player-Listplayer你在players.


推荐阅读