在这个Vue 3和TypeScript应用程序中,导致切片的原因不是函数错误?

rkkpypqq  于 2023-06-06  发布在  Vue.js
关注(0)|答案(1)|浏览(129)

我一直在使用Vue 3TypeScriptThe Movie Database(TMDB)API开发SPA。
src\components\MovieDetails.vue中,我有:

<template>
  <div class="row">
    <div class="col-sm-4 col-md-3">
      <div class="poster-container text-center text-sm-start my-3">
        <img v-if="movie"
          :src="genericPoster"
          :alt="movie?.title"
          class="img-fluid shadow-sm"
        />
      </div>
    </div>

    <div class="col-sm-8 col-md-9">
      <h1 class="movie-title mt-4">{{ movie?.original_title }}</h1>

      <p v-if="movie?.genres.length">
        <strong class="pe-1">Genres:</strong>
        <span
          class="badge bg-secondary"
          v-for="genre in movie?.genres"
          :key="genre.id"
          >{{ genre.name }}</span
        >
      </p>

      <p v-if="movie?.vote_average" class="user-score">
        <strong>User Score:</strong>
        <span class="score" :class="movieQuality">{{
          Number(movie?.vote_average).toFixed(2)
        }}</span>
      </p>

      <div v-if="movie?.overview">
        <h2 class="section-title">Overview</h2>
        <p>{{ movie.overview }}</p>
      </div>

      <div v-if="movieTrailers.length" class="mb-3">
        <h2 class="section-title">Trailers</h2>
        <TrailerCarousel :movieTrailers="movieTrailers" />
      </div>

      <div v-if="movieCast.length" class="cast-container">
        <h2 class="section-title">Cast</h2>
        <div class="row">
          <div
            v-for="actor in movieCast.slice(0, 12)"
            :key="actor['id']"
            class="col-sm-3"
          >
            <ActorCard :actor="actor" />
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import { useRoute } from "vue-router";
import env from "../env";
import { Movie } from "@/models/Movie";
import { Trailer } from "@/models/Trailer";
import { MovieCast } from "@/models/MovieCast";
import TrailerCarousel from "./TrailerCarousel.vue";
import ActorCard from "./ActorCard.vue";

export default defineComponent({
  name: "MovieDetails",

  components: {
    TrailerCarousel,
    ActorCard,
  },

  data: () => ({
    route: useRoute(),
    genericPosterBig: require('../assets/generic-poster.png'),
    movie: null as Movie | null,
    movieQuality: String as unknown | 'bad',
    movieCast: Array as unknown | MovieCast[]
    movieTrailers: Array as unknown | Trailer[]
  }),

  mounted() {
    this.getMovieDetails();
    this.getMovieTrailers();
    this.getMovieCast();
  },

  methods: {
    getMovieDetails() {
      this.$axios
        .get(
          `${env.api_url}/movie/${this.route.params.id}?api_key=${env.api_key}`
        )
        .then((response) => {
          this.movie = response.data;
          // Once you get the movie, set its quality
          this.setMovieQuality();
        })
        .catch((err) => console.log(err));
    },

    setMovieQuality() {
      if (Number(this.movie?.vote_average) >= 7) {
         this.movieQuality = 'good';
      } else if(Number(this.movie?.vote_average) < 7 && Number(this.movie?.vote_average) > 5.5) {
         this.movieQuality =  'average';
      } else {
         this.movieQuality =  'bad';
      }
    },

    getMovieTrailers() {
      this.$axios
        .get(
          `${env.api_url}/movie/${this.route.params.id}/videos?api_key=${env.api_key}`
        )
        .then((response) => {
          this.movieTrailers = response.data.results;
        })
        .catch((err) => console.log(err));
    },

    getMovieCast() {
      this.$axios
        .get(
          `${env.api_url}/movie/${this.route.params.id}/credits?api_key=${env.api_key}`
        )
        .then((response) => {
          this.movieCast = response.data.cast;
        })
        .catch((err) => console.log(err));
    },
  },

  computed: {
    genericPoster() {
      return !this.movie?.poster_path
        ? this.genericPosterBig
        : `https://image.tmdb.org/t/p/w500/${this.movie?.poster_path}`
    },
  },

  watch: {
    "$route.params.id"() {
      this.getMovieDetails();
      this.getMovieTrailers();
      this.getMovieCast();
    },
  },
});
</script>

src\models\MovieCast.ts中:

export interface MovieCast {
    adult?: boolean;
    character?: string;
    name?: string;
    profile_path?: string;
}

代替组件中的这两行

movieCast: Array as unknown | MovieCast[]
movieTrailers: Array as unknown | Trailer[]

我曾经有过:

movieTrailers: [],
movieCast: [],

我已经做了改变,这样我就有了一个更严格/强类型的应用程序。
问题
更改后,控制台显示错误:
TypeError:_ctx.movieCast.slice不是函数

<div
    v-for="actor in movieCast.slice(0, 12)"
    :key="actor['id']"
    class="col-sm-3"
  >
    <ActorCard :actor="actor" />
</div>

还有一个**Stackblitz**,与工作应用程序。

常见问题

1.我做错了什么?
1.解决此问题最可靠的方法是什么?

e0bqpujr

e0bqpujr1#

如果你正在分配一个非数组,你也会得到一个错误。尝试记录类型,看看实际返回的是什么。

console.log('movieCast', response.data.cast)
this.movieCast = response.data.cast;

使用conditional operator来防止异步值为undefined并计算时出错。您也可以将v-for Package 在v-if中并检查undefined。

v-for="actor in movieCast?.slice(0, 12)"

相关问题