You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Vue.js中调用TVmaze API按类型获取并展示剧集?

Solution: Fetch & Filter TVMaze Shows by Genre in Vue.js

Since the TVMaze API doesn’t have a direct genre filter endpoint, we’ll need to fetch paginated show data and filter it client-side to get 4 shows each for Action, Drama, and Thriller genres. Here’s a step-by-step implementation using Vue.js (I’ll use Axios for simplicity, but native fetch works too):

Step 1: Set Up Dependencies (Optional)

If you aren’t already using Axios, install it via npm or yarn:

npm install axios
# or
yarn add axios

Step 2: Complete Vue Component Implementation

This component handles fetching, filtering, loading states, errors, and displays the results neatly:

<template>
  <div class="show-library">
    <!-- Loading State -->
    <div v-if="isLoading" class="status-message">Grabbing your shows...</div>
    
    <!-- Error State -->
    <div v-if="error" class="status-message error">Oops! {{ error }}</div>
    
    <!-- Filtered Show Sections -->
    <div v-else class="genre-sections">
      <section class="genre-section">
        <h2>Action Picks (4)</h2>
        <div class="show-grid">
          <div v-for="show in actionShows" :key="show.id" class="show-card">
            <img :src="show.image?.medium || 'https://via.placeholder.com/200x300'" :alt="show.name">
            <h3>{{ show.name }}</h3>
            <p>Rating: {{ show.rating.average || 'N/A' }}</p>
          </div>
        </div>
      </section>

      <section class="genre-section">
        <h2>Drama Picks (4)</h2>
        <div class="show-grid">
          <div v-for="show in dramaShows" :key="show.id" class="show-card">
            <img :src="show.image?.medium || 'https://via.placeholder.com/200x300'" :alt="show.name">
            <h3>{{ show.name }}</h3>
            <p>Rating: {{ show.rating.average || 'N/A' }}</p>
          </div>
        </div>
      </section>

      <section class="genre-section">
        <h2>Thriller Picks (4)</h2>
        <div class="show-grid">
          <div v-for="show in thrillerShows" :key="show.id" class="show-card">
            <img :src="show.image?.medium || 'https://via.placeholder.com/200x300'" :alt="show.name">
            <h3>{{ show.name }}</h3>
            <p>Rating: {{ show.rating.average || 'N/A' }}</p>
          </div>
        </div>
      </section>
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  name: 'GenreShowFilter',
  data() {
    return {
      actionShows: [],
      dramaShows: [],
      thrillerShows: [],
      isLoading: true,
      error: null,
      currentPage: 1,
      targetPerGenre: 4 // We want exactly 4 shows per category
    };
  },
  mounted() {
    // Start fetching when the component loads
    this.fetchAndFilterShows();
  },
  methods: {
    async fetchAndFilterShows() {
      try {
        // Fetch the current page of shows (25 per page from TVMaze)
        const res = await axios.get(`http://api.tvmaze.com/shows?page=${this.currentPage}`);
        const shows = res.data;

        // Filter shows into their respective genre lists (only if we haven't hit the target yet)
        shows.forEach(show => {
          if (this.actionShows.length < this.targetPerGenre && show.genres.includes('Action')) {
            this.actionShows.push(show);
          }
          if (this.dramaShows.length < this.targetPerGenre && show.genres.includes('Drama')) {
            this.dramaShows.push(show);
          }
          if (this.thrillerShows.length < this.targetPerGenre && show.genres.includes('Thriller')) {
            this.thrillerShows.push(show);
          }
        });

        // Check if we have enough shows in all categories
        const hasEnoughShows = 
          this.actionShows.length >= this.targetPerGenre &&
          this.dramaShows.length >= this.targetPerGenre &&
          this.thrillerShows.length >= this.targetPerGenre;

        if (!hasEnoughShows) {
          // Increment page and keep fetching
          this.currentPage++;
          this.fetchAndFilterShows();
        } else {
          // Trim any extra shows (in case we grabbed more than 4)
          this.actionShows = this.actionShows.slice(0, this.targetPerGenre);
          this.dramaShows = this.dramaShows.slice(0, this.targetPerGenre);
          this.thrillerShows = this.thrillerShows.slice(0, this.targetPerGenre);
          this.isLoading = false;
        }
      } catch (err) {
        this.error = 'Failed to load shows. Please try again later.';
        this.isLoading = false;
        console.error('Fetch error:', err);
      }
    }
  }
};
</script>

<style scoped>
.show-library {
  max-width: 1200px;
  margin: 2rem auto;
  padding: 0 1rem;
}

.status-message {
  text-align: center;
  padding: 3rem;
  font-size: 1.2rem;
}

.status-message.error {
  color: #dc3545;
}

.genre-sections {
  display: flex;
  flex-direction: column;
  gap: 2rem;
}

.genre-section h2 {
  border-bottom: 2px solid #eee;
  padding-bottom: 0.5rem;
}

.show-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 1.5rem;
  margin-top: 1rem;
}

.show-card {
  border: 1px solid #eee;
  border-radius: 8px;
  padding: 1rem;
  text-align: center;
  transition: transform 0.2s;
}

.show-card:hover {
  transform: translateY(-5px);
}

.show-card img {
  width: 100%;
  border-radius: 4px;
  margin-bottom: 0.5rem;
}

.show-card h3 {
  margin: 0 0 0.5rem;
  font-size: 1rem;
}
</style>

Key Features Explained:

  • Smart Pagination: We fetch pages one by one until we hit 4 shows per genre—no need to load unnecessary data once our target is met.
  • Genre Matching: Each show has a genres array; we check if it contains our target genre before adding it to the list.
  • User Feedback: Clear loading and error states keep users informed while data loads.
  • Fallback Images: Uses a placeholder image if a show doesn’t have a medium-sized image available.

Quick Swap to Native Fetch:

If you don’t want to use Axios, replace the fetch call with:

const res = await fetch(`http://api.tvmaze.com/shows?page=${this.currentPage}`);
const shows = await res.json();

内容的提问来源于stack exchange,提问作者machupichu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 22:47:49