如何调用API获取所需数据并减少Vue.js中的监听器数量
Hey there! Let's break down how to solve both of your issues step by step.
1. Modify the API Call to Fetch Full Anime Data
Right now, your animeFind function only extracts the image URL. We'll adjust it to store the complete anime object (including title, episode count, synopsis, etc.) so you can access all the data you need. If you want detailed episode lists (not just the total count), we can also add an optional call to Jikan's episodes endpoint.
2. Avoid Extra Vue Watchers
Instead of writing duplicate watchers for anime1 and anime2, we'll reuse a single handler function. This makes scaling easier if you ever need to add more anime entries later—no extra watchers required.
Modified Component Code
Here's the updated code with both changes implemented:
<template> <section class="container"> <!-- Anime 1 Column --> <div class="column" v-if="animeData1"> <img :src="animeData1.image_url" alt="Anime 1 cover" /> <h2>{{ animeData1.title }}</h2> <p>Total Episodes: {{ animeData1.episodes }}</p> <p>{{ animeData1.synopsis }}</p> <!-- Optional: Show truncated episode list if fetched --> <div v-if="animeData1.episodesList"> <h3>Latest Episodes</h3> <ul> <li v-for="ep in animeData1.episodesList.slice(-5)" :key="ep.episode_id"> Ep {{ ep.episode_id }}: {{ ep.title }} </li> </ul> </div> </div> <!-- Anime 2 Column --> <div class="column" v-if="animeData2"> <img :src="animeData2.image_url" alt="Anime 2 cover" /> <h2>{{ animeData2.title }}</h2> <p>Total Episodes: {{ animeData2.episodes }}</p> <p>{{ animeData2.synopsis }}</p> <!-- Optional: Show truncated episode list if fetched --> <div v-if="animeData2.episodesList"> <h3>Latest Episodes</h3> <ul> <li v-for="ep in animeData2.episodesList.slice(-5)" :key="ep.episode_id"> Ep {{ ep.episode_id }}: {{ ep.title }} </li> </ul> </div> </div> <!-- Error Display --> <div v-if="error" class="notification is-danger">{{ error.message }}</div> </section> </template> <script> import axios from "axios"; import Buefy from "buefy"; import "buefy/dist/buefy.css"; import Vue from "vue"; Vue.use(Buefy); export default { props: { anime1: String, anime2: String, }, data() { return { // Store full anime objects instead of just image URLs animeData1: null, animeData2: null, error: null, }; }, methods: { async fetchAnimeData(searchQuery, targetKey) { try { // First search for the anime to get its MAL ID const searchResponse = await axios.get(`https://api.jikan.moe/v3/search/anime?q=${searchQuery}`); const animeId = searchResponse.data.results[0].mal_id; // Fetch core anime details const animeDetails = await axios.get(`https://api.jikan.moe/v3/anime/${animeId}`); this[targetKey] = animeDetails.data; // Optional: Fetch detailed episode list (uncomment to enable) // const episodeData = await axios.get(`https://api.jikan.moe/v3/anime/${animeId}/episodes`); // this[targetKey].episodesList = episodeData.data.episodes; } catch (err) { this.error = err; console.error("Failed to fetch anime data:", err); } }, }, watch: { // Reuse the same handler logic for both props anime1: { immediate: true, handler(newVal) { if (newVal) this.fetchAnimeData(newVal, "animeData1"); }, }, anime2: { immediate: true, handler(newVal) { if (newVal) this.fetchAnimeData(newVal, "animeData2"); }, }, }, }; </script>
Key Improvements:
- Switched to
async/awaitfor cleaner, more readable asynchronous code (no nested.then()chains) - Stored full anime objects in
dataso you can access any field from the API response (title, synopsis, episode count, etc.) - Used conditional rendering (
v-if) to avoid showing empty content before data loads - Reused a single
fetchAnimeDatamethod for both anime entries, cutting down on duplicate code - Added an optional episode list fetch (commented out) for when you need detailed episode information
If you ever need to add more anime entries (like anime3), you only need to:
- Add the new prop (e.g.,
anime3: String) - Add a new data property (e.g.,
animeData3: null) - Add a new watch entry using the same
fetchAnimeDatamethod—no new handler logic required!
内容的提问来源于stack exchange,提问作者A.K.M. Adib

