Vue.js 实战:构建一个电影搜索和过滤应用

应用场景介绍

本应用旨在提供一个简洁易用的界面,用户可以在其中搜索和过滤电影,基于类型、评分等条件进行筛选,并查看电影详细信息。

代码基本功能介绍

该代码使用 Vue.js 框架和一系列 UI 组件构建,包括:

  • 搜索栏用于搜索电影标题
  • 下拉菜单用于过滤电影类型和评分
  • 卡片组件显示搜索结果,包括电影图像、标题和价格

功能实现步骤及关键代码分析

1. 安装依赖项

首先,安装必要的依赖项:

npm install vue vue-router vuex echarts echarts-for-vue @wangeditor/editor-for-vue v-calendar vue3-baidu-map-gl

2. 构建 Vuex 存储

Vuex 存储用于管理应用状态,包括搜索查询、过滤器和搜索结果:

const store = new Vuex.Store({
  state: {
    search: "",
    genre: "All",
    rating: "All",
    results: [],
  },
  mutations: {
    setSearch(state, payload) {
      state.search = payload;
    },
    setGenre(state, payload) {
      state.genre = payload;
    },
    setRating(state, payload) {
      state.rating = payload;
    },
    setResults(state, payload) {
      state.results = payload;
    },
  },
  actions: {
    searchMovies({ commit }, payload) {
      // 这里可以调用 API 获取实际的搜索结果
      const results = [
        {
          id: 1,
          image: "https://source.unsplash.com/random/200x200",
          title: "The Shawshank Redemption",
          price: "$10.99",
        },
        {
          id: 2,
          image: "https://source.unsplash.com/random/200x200",
          title: "The Godfather",
          price: "$12.99",
        },
        {
          id: 3,
          image: "https://source.unsplash.com/random/200x200",
          title: "The Dark Knight",
          price: "$14.99",
        },
        {
          id: 4,
          image: "https://source.unsplash.com/random/200x200",
          title: "12 Angry Men",
          price: "$16.99",
        },
      ];
      commit("setResults", results);
    },
  },
});

3. 构建 Vue 组件

搜索栏组件:

<template>
  <div class="flex items-center justify-between px-4 py-2 border-b border-gray-200">
    <van-search v-model="search" placeholder="Search" class="w-full" />
    <van-icon name="magnifying-glass" class="text-gray-500" />
  </div>
</template>

<script>
import { ref } from "vue";

export default {
  setup() {
    const search = ref("");
    return { search };
  },
};
</script>

下拉菜单组件:

<template>
  <van-dropdown-menu
    v-model="value"
    :options="options"
    placeholder="Placeholder"
    class="w-full"
  />
</template>

<script>
import { ref } from "vue";

export default {
  props: {
    value: {
      type: String,
      default: "All",
    },
    options: {
      type: Array,
      required: true,
    },
    placeholder: {
      type: String,
      default: "All",
    },
  },
  setup(props) {
    return {
      value: props.value,
      options: props.options,
      placeholder: props.placeholder,
    };
  },
};
</script>

卡片组件:

<template>
  <van-card
    :thumb="thumb"
    :title="title"
    :price="price"
  />
</template>

<script>
export default {
  props: {
    thumb: {
      type: String,
      default: "",
    },
    title: {
      type: String,
      default: "",
    },
    price: {
      type: String,
      default: "",
    },
  },
};
</script>

4. 构建主应用组件

主应用组件负责组合其他组件并处理搜索和过滤逻辑:

<template>
  <div class="bg-gray-100">
    <van-nav-bar
      title="Search"
      left-arrow
      fixed
      :border="false"
      class="bg-white"
    />
    <search-bar @search="onSearch" />
    <div
      class="flex items-center justify-between px-4 py-2 border-b border-gray-200"
    >
      <genre-dropdown-menu
        v-model="genre"
        :options="genreOptions"
        placeholder="Genre: All"
        class="w-full"
      />
      <rating-dropdown-menu
        v-model="rating"
        :options="ratingOptions"
        placeholder="Rating: All"
        class="w-full"
      />
    </div>
    <div class="flex flex-wrap justify-center px-4 py-2">
      <card
        v-for="item in results"
        :key="item.id"
        :thumb="item.image"
        :title="item.title"
        :price="item.price"
      />
    </div>
  </div>
</template>

<script>
import SearchBar from "./SearchBar.vue";
import GenreDropdownMenu from "./GenreDropdownMenu.vue";
import RatingDropdownMenu from "./RatingDropdownMenu.vue";
import Card from "./Card.vue";
import { ref } from "vue";
import { mapActions } from "vuex";

export default {
  components: { SearchBar, GenreDropdownMenu, RatingDropdownMenu, Card },
  setup() {
    const genre = ref("All");
    const rating = ref("All");
    const results = ref([]);
    const genreOptions = ["All", "Action", "Comedy", "Drama", "Horror", "Romance"];
    const ratingOptions = ["All", "1", "2", "3", "4", "5"];

    const { searchMovies } = mapActions(["searchMovies"]);

    const onSearch = (searchQuery) => {
      searchMovies({ searchQuery, genre, rating });
    };

    return {
      genre,
      rating,
      results,
      genreOptions,
      ratingOptions,
      onSearch,
    };
  },
};
</script>

总结与展望

开发经验与收获:

  • 掌握了 Vue.js 中组件通信和状态管理的基本概念。
  • 了解了如何使用第三方 UI 组件库来快速构建复杂的 UI。
  • 提升了对 JavaScript 和 Vue.js 生态系统的理解。

未来拓展与优化:

  • **集成 API:**将实际的 API 集成到应用中,以获取和过滤电影数据。
  • **添加分页:**当搜索结果较多时,添加分页功能以提高用户体验。
  • **实现排序:**允许用户根据评分、上映日期等条件对搜索结果进行排序。
  • **响应式设计:**优化应用在不同屏幕尺寸上的显示效果。
Login
ECHO recommendation
ScriptEcho.ai

User Annotations

影片搜索结果页