Как я могу сделать части шаблона многократно используемого компонента необязательными в приложении Vue 3?

Я работаю над SPA с API Vue 3, TypeScript и The Movie Database (TMDB).

У меня есть компонент карты фильма (MovieCard.vue), который я использую (как минимум) в двух разных контекстах, и я хочу, чтобы он вел себя немного по-разному в зависимости от контекста.

<template>
  <div class = "movie card" @click = "showDetails(movie.id)">
    <div class = "thumbnail">
      <img
        :src = "movieCardImage"
        :alt = "movie.title"
        class = "img-fluid"
      />
    </div>

    <div class = "card-content">
      <h2 class = "card-title">{{ movie.title }}</h2>
      <p class = "card-desc">{{ movie.overview }}</p>
      <span :title = "`Score: ${movie.vote_average}`" class = "score">{{ movie.vote_average}}</span>
    </div>

    <div class = "card-footer">
      <p class = "m-0 release">
        Release date: {{ dateTime(movie.release_date) }}
      </p>
      <p v-if = "movieGenres" class = "m-0 pt-1">
        <span class = "genre" v-for = "genre in movieGenres" :key = "genre.id">
          {{ genre.name }}
        </span>
      </p>
    </div>
  </div>
</template>

<script lang = "ts">
import { defineComponent } from "vue";
import moment from "moment";

export default defineComponent({
  name: "MovieCard",

  props: {
    movie: {
      type: Object,
      required: true,
    },

    genres: {
      type: Object,
      required: false,
    },
  },

  data: () => ({
    genericCardImage: require("../assets/generic-card-image.png"),
  }),

  methods: {
    dateTime(value: any) {
      return moment(value).format("MMMM DD, YYYY");
    },

    showDetails(movie_id: any) {
      let movie_url = `movie/${movie_id}`;
      window.open(movie_url, "_self");
    },
  },

  computed: {
    movieCardImage() {
      return !this.movie?.backdrop_path
        ? this.genericCardImage
        : `https://image.tmdb.org/t/p/w500/${this.movie?.backdrop_path}`;
    },

    movieGenres() {
      if (this.genres) {
        let genres = this.genres;
        return this.movie?.genre_ids
          .filter((genre_id: number) => genre_id in genres)
          .map((genre_id: number) => genres[genre_id])
          .filter((genre: { name: string }) => genre.name.length > 0);
      } else {
        return [];
      }
    },
  },
});
</script>

Первый контекст — это компонент MoviesList.vue.

<template>
  <div class = "row list">
    <div
      v-for = "movie in movies"
      :key = "movie.id"
      class = "col-xs-12 col-sm-6 col-lg-4 col-xl-3"
    >
      <MovieCard :movie = "movie" :genres = "genres" />
    </div>
  </div>
</template>

<script lang = "ts">
import { defineComponent } from "vue";
import axios from "axios";
import env from "../env";
import MovieCard from "./MovieCard.vue";

export default defineComponent({
  name: "MoviesList",
  components: { MovieCard },

  props: {
    listType: {
      type: String,
      required: true,
    },
  },

  data: () => ({
    searchTerm: "",
    movies: [],
    genres: [],
  }),

  mounted() {
    this.listMovies();
    this.getGenres();
  },

  methods: {
    listMovies() {
      axios
        .get(
          `${env.api_url}/movie/${this.$props.listType}?api_key=${env.api_key}`
        )
        .then((response) => {
          this.movies = response.data.results;
        })
        .catch((err) => console.info(err));
    },

    getGenres() {
      axios
        .get(`${env.api_url}/genre/movie/list?api_key=${env.api_key}`)
        .then((response) => {
          this.genres = response.data.genres;
        })
        .catch((err) => console.info(err));
    },
  },
});
</script>

Результат:

Второй контекст — это компонент ActorDetails.vue, где я хочу, чтобы он отображался без среднего «пузыря» голосов:

<div v-if = "knownFor" class = "movies">
    <h2 class = "section-title">Known For</h2>
    <div class = "row list">
        <div
            v-for = "item in knownFor"
            :key = "item.id"
            class = "col-xs-12 col-sm-6 col-lg-4 col-xl-3"
        >
            <MovieCard :movie = "item" />
        </div>
    </div>
</div>

Желаемый результат:

Stackblitz

Вы можете увидеть Stackblitz ЗДЕСЬ.

Цель

Я хочу сделать эту часть компонента карточки фильма необязательной:

<span :title = "`Score: ${movie.vote_average}`" class = "score">{{ movie.vote_average}}</span>

Я попробовал «очевидный» способ в компоненте ActorDetails, но он не работает (из-за стилей с ограниченной областью действия, которые я предпочитаю сохранять):

.score {
    display: none !important;
}

Каков простой и надежный способ достижения этой цели?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
134
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Кто-то более опытный может опубликовать лучший ответ, но я попробую. Если я правильно понял вашу проблему, вы хотите показывать рейтинг каждого фильма только тогда, когда пользователь находится в «общем» списке фильмов, и скрывать его, когда пользователь находится в списке актеров. Вы можете добавить еще один реквизит к компоненту movieCard как логическое значение и передать его как true/false в зависимости от того, хотите ли вы, чтобы у карты был рейтинг или нет.

<span v-if = "showRating" :title = "`Score: ${movie.vote_average}`" class = "score d-flex">{{movie.vote_average}}</span>

и на реквизите

showRating: {
   type: Boolean,
   default: false,
},

а затем в компоненте MoviesList:

<MovieCard :showRating = "true" :movie = "movie" :genres = "genres" />

Очень простое и надежное решение. Именно то, что я искал. :)

Razvan Zamfir 10.05.2023 15:05
:showRating = "true" можно сократить до showRating для логической опоры, но в остальном все так просто.
Estus Flask 10.05.2023 19:09

Другие вопросы по теме

Похожие вопросы

Реагировать: как я могу выполнять функцию точно в минуту каждый час?
Заставить холст использовать доступное пространство в столбце flex
Удалить круг, выбранный в кнопке
Есть ли способ оживить это как работающий конвейер?
Как я могу предотвратить временную загрузку изображения-заполнителя в этом приложении Vue 3?
Как разобрать таблицу спряжения глаголов французского Викисловаря (довольно сложная HTML-таблица) в JSON?
Как я могу исправить проблему с выборкой в ​​моем коде, у меня проблемы, и я не могу продолжить работу над этим сайтом
Когда я нажимаю тег привязки, мне нужно перейти на другую страницу, и на этой странице мне нужно показать модальное окно с использованием Javascript
Конкатенация строки с использованием цикла for заставляет ее начинаться с «неопределенного»? (javascript)
Тип ввода = "время" возвращает NAN, если получить только значение часов