如何阻止Vuetify中v-hover触发自定义函数
Hey there! Let's break down why your getMovieGenre function keeps triggering every time you hover over the card, and fix it for good.
Why this is happening
Template expressions like {{ getMovieGenre(movie.genres) }} run every time your component re-renders. When you use v-hover, the hover state changes on mouse enter/exit, which triggers a re-render of the component. That means your function gets called over and over again—wasting performance and causing unnecessary computations.
Fixes you can implement (from best to easiest)
1. Preprocess your movie data (Recommended)
The cleanest approach is to calculate the formatted genre string once when you load your movie data, instead of calculating it on every render. You can do this in a lifecycle hook like created or right after fetching your movies:
// Inside your component's script created() { // Assuming your movies are stored in a reactive property this.movies = this.movies.map(movie => ({ ...movie, // Compute the genre string once and store it formattedGenres: this.getMovieGenre(movie.genres) })) } // Then in your template, just use the precomputed property <v-card-subtitle>{{ movie.formattedGenres }}</v-card-subtitle>
Now, no matter how many times the component re-renders (from hover or other changes), you're just referencing a precomputed string—no function calls needed.
2. Use a computed property
If your movie list is reactive (e.g., it might update after the component loads), a computed property is a great choice. Computed properties cache their results, so they only re-run when their dependencies change (not on every re-render):
// Inside your component's script computed: { processedMovies() { return this.movies.map(movie => ({ ...movie, formattedGenres: this.getMovieGenre(movie.genres) })) } }
Then in your template, loop over processedMovies instead of the original movies array. This way, the genre strings are only recalculated if the movies array itself changes.
3. Memoize the function (Last resort)
If you absolutely have to call the function directly in the template, you can add memoization to it. Memoization caches the result of the function based on its input, so it won't re-run with the same genres value:
You can use Lodash's memoize utility, or write a simple version yourself:
// Using Lodash import _ from 'lodash' export default { methods: { getMovieGenre: _.memoize(function(genres) { // Your existing logic here (e.g., filter and join genres) return genres.filter(genre => genre.isActive).join(', ') }) } } // Or a simple custom memoizer export default { methods: { getMovieGenre(genres) { if (!this.genreCache) this.genreCache = {} const key = JSON.stringify(genres) if (!this.genreCache[key]) { this.genreCache[key] = genres.filter(genre => genre.isActive).join(', ') } return this.genreCache[key] } } }
Note: This still calls the function on every render, but it skips the actual computation if the input hasn't changed. It's not as efficient as preprocessing, but it works if you can't modify the movie data upfront.
内容的提问来源于stack exchange,提问作者AVIRAM HAG

