迭代中的自定义元素需要 Vue.js 中的“v-bind:key”指令

Iva*_*vić 1 javascript vue.js visual-studio-code

我对 Vue.js 有疑问。我怎样才能解决这个问题?我在文档中没有找到任何内容。我收到此错误:“[vue/require-v-for-key] 迭代中的元素期望具有 'v-bind:key' 指令。”

这是:“迭代中的元素期望有‘v-bind:key’指令。”

我的 Roulette.vue 有这个

<template>
  <div class="roulette">
    <h1>Roulette</h1>
    <div class="radio" v-for="genre in genres"> **here**
      <input 
        @change="onGenrePick"
        type="radio"
        name="genre"
        v-bind:id="genre.id"
        v-bind:value="genre.id">
      <label v-bind:for="genre.id">{{genre.name}}</label>
    </div>
    <Button class="btn" :onClick="roll">Roll</Button>

    <MovieCard 
      v-if="!!movie"
      v-bind:image="serviceGetImagePath(movie.poster_path)"
      v-bind:title="movie.title"
      v-bind:releaseDate="serviceFormatYear(movie.release_date)"
      v-bind:id="movie.id"
      v-bind:voteAverage="movie.vote_average"/>
  </div>
</template>

<script>
  import MovieCard from '../components/MovieCard'
  import Button from '../components/Button'
  import {movieService} from '../mixins/movieService'

  export default {

    name: 'Roulette',
    components: {Button, MovieCard},
    mixins: [movieService],
    mounted: async function () {
      this.genres = await this.serviceGetGenres()
    },
    data: () => ({
      genres: [],
      pickedGenres: new Set(),
      movie: null
    }),
    methods: {
      async roll() {
        const genreIds = Array.from(this.pickedGenres)
        const movies = await this.serviceGetMoviesByGenre(genreIds)
        this.movie = movies[this.getRandom(movies.length)]
      },
      onGenrePick(e) {
        this.pickedGenres.add(e.target.value)
      },
      getRandom(max) {
        return Math.floor(Math.random() * max - 1)
      }
    }
  }
</script>

<style scoped lang="scss">
  .roulette {
    margin: 40px;
  }

  .btn {
    display: block;
    min-width: 220px;
  }

  .radio {
    display: inline-block;
    margin: 20px 10px;

    > label {
      margin-left: 5px;
    }
  }
</style>
Run Code Online (Sandbox Code Playgroud)

在我的 UpcomingMovies.vue 中

<template>
  <div class="wrapper" v-if="movies.length">
    <MovieCard 
      v-for="movie in movies" **here**
      v-bind:image="serviceGetImagePath(movie.poster_path)"**here**
      v-bind:title="movie.title"**here**
      v-bind:releaseDate="serviceFormatYear(movie.release_date)"**here**
      v-bind:id="movie.id"**here**
      v-bind:voteAverage="movie.vote_average"/>**here**
    <div class="loader">
      <Button class="loader__btn" :onClick="loadNextPage">Load</Button>
    </div>
    <router-link :to="routes.roulette.path">
      <div class="roulette">
        <img src="../assets/roulette.png" alt="Roulette">
      </div>
    </router-link>
  </div>
  <Loader v-else/>
</template>

<script>
  import Button from '../components/Button'
  import MovieCard from '../components/MovieCard'
  import Loader from '../components/Loader'
  import { movieService } from '../mixins/movieService'
  import routes from '../router/routes'

  export default {

    name: 'UpcomingMovies',
    mixins: [movieService],
    components: { Button, MovieCard, Loader },
    data: () => ({
      movies: [],
      page: 1,
      routes
    }),
    mounted() {
      this.getMovies(this.page)
    },
    methods: {
      getMovies: async function (page) {
        const movies = await this.serviceGetMovies(page)
        this.movies.push(...movies)
      },
      loadNextPage() {
        this.getMovies(++this.page)
      }
    }
  }
</script>

<style scoped lang="scss">
  .wrapper {
    width: 100%;
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    margin-top: 40px;
    margin-bottom: 40px;
  }
  .loader {
    width: 100%;
    text-align: center;
    margin-top: 40px;
    margin-bottom: 40px;
    &__btn {
      border: 5px dashed white;
      background-color: transparent;
      border-radius: 50%;
      width: 80px;
      height: 80px;
      font-weight: bold;
      text-transform: uppercase;
      transition: border-radius 100ms ease-in-out, width 120ms ease-in-out 120ms;
      &:hover {
        border-radius: 0;
        background-color: rgba(white, 0.1);
        width: 200px;
      }
    }
  }
  .roulette {
    cursor: pointer;
    position: fixed;
    right: 25px;
    bottom: 25px;
    > img {
      opacity: .8;
      animation: rotate 5s infinite;
      width: 70px;
      height: auto;
      transition: opacity 220ms linear;
      &:hover {
        opacity: 1;
      }
    }
  }
  @keyframes rotate {
    0% {
      transform: rotate(0);
    }
    100% {
      transform: rotate(360deg);
    }
  }
</style>
Run Code Online (Sandbox Code Playgroud)

Aer*_*er0 6

Vue 在内部使用keys每个循环的唯一性来确定在更新过程中的哪个点更新哪个元素。因此,每个人都v-for需要一个v-bind:key属性才能正常工作。在您的特殊情况下,这将如下所示:

<div class="radio" v-for="genre in genres" v-bind:key="someUniqueId"> **here**
Run Code Online (Sandbox Code Playgroud)

您可以使用当前循环索引作为 ID 或其他任何内容。