user 前端movie/movieClassics.Vue实现和电影列表的渲染

本文展示了如何使用Vue.js构建一个电影分类查询应用,包括顶部导航菜单、电影类型的筛选、按上映时间排序功能。组件化设计使得电影列表能够根据条件动态加载,同时实现了电影海报的悬停效果和详细信息预览。代码中使用了axios进行API调用,获取电影类别数据,并通过watch监听器实时更新查询条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

界面

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

在这里插入图片描述

在这里插入图片描述

movie.vue

<template>
  <el-container>
    <el-header>
<!--      上端的菜单栏-->
      <el-menu :default-active="$route.path"
               class="nav-menu"
               mode="horizontal"
               :router="true"
               background-color="#545c64"
               text-color="#fff"
               active-text-color="#ffd04b">
        <el-menu-item :index="item.path" v-for="item in menuList" :key="item.id">{{item.name}}</el-menu-item>
      </el-menu>
    </el-header>

    <el-main>
      <!-- 类别查询 -->
      <div class="tags-container">
        <div class="tags-line">
          <div class="tags-title">类型:</div>
          <el-radio-group v-model="categoryRadio">
<!--            显示所有的类型-->
            <el-radio-button :label="0">全部</el-radio-button>
            <el-radio-button :label="item.movieCategoryId" v-for="item in categoryList" :key="item.movieCategoryId">{{item.movieCategoryName}}</el-radio-button>
          </el-radio-group>
        </div>
      </div>

      <!-- 按条件排序 -->
<!--      <div class="order-by-container">-->
<!--        <el-radio v-model="orderByColumn" label="releaseDate">按时间排序</el-radio>-->
<!--&lt;!&ndash;        <el-radio v-model="orderByColumn" label="movieScore">按评价排序</el-radio>&ndash;&gt;-->
<!--      </div>-->
<!--      <router-view :movieCategoryId="categoryRadio" :movieAreaId="areaRadio" :movieAgeId="ageRadio" :orderByColumn="orderByColumn"></router-view>-->

      <!--     显示电影(根据类别,排序:根据上映时间)-->
      <router-view :movieCategoryId="categoryRadio" :orderByColumn="orderByColumn"></router-view>
    </el-main>
  </el-container>
</template>

<script>
export default {
  name: "Movie",
  data(){
    return {
      menuList: [
        {
          id: '1',
          name: '正在热映',
          path: '/movie/movieOngoing'
        },
        {
          id: '2',
          name: '即将上映',
          path: '/movie/movieUpcoming'
        },
        {
          id: '3',
          name: '经典影片',
          path: '/movie/movieClassics'
        }
      ],
      categoryRadio: 0,
      categoryList: [],
      orderByColumn: 'releaseDate'
    }
  },
  created() {
    //获得所有电影类别
    this.getCategoryList()
  },
  methods: {
    async getCategoryList() {
      const { data : res } = await axios.get('sysMovieCategory/find')
      if(res.code !== 200) return this.$message.error('获取服务器信息失败')
      this.categoryList = res.data
    }
  },
  watch:{
    '$route'(){
      //页面发生变化时初始化类别选项
      this.categoryRadio = 0
      this.orderByColumn = 'releaseDate'
    }
  }
}
</script>

<style scoped>
.el-header{
  padding: 0px;
}

.nav-menu{
  display: flex;
  justify-content: space-around;
}

.el-menu-item{
  font-size: 16px;
}

.el-menu-item:hover{
  color: #FFFFFF !important;
}

.el-main{
  width: 1200px;
  margin: 0 auto;
}

.tags-container{
  border: solid #EEEEEE 1px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1)
}

.tags-line{
  width: 100%;
  display: flex;
  padding: 10px;
  box-sizing: border-box;
  border-bottom: solid #EEEEEE 1px;
}

.tags-line:last-child{
  border-bottom: 0;
}

.tags-title {
  width: 5%;
  height: 24px;
  line-height: 24px;
  float: left;
  color: #999;
  font-size: 14px;
}

.el-radio-group{
  width: 92%;
  margin-left: 20px;
}

.el-radio-button {
  margin-right: 10px;
}

.el-radio-button:last-child{
  margin-right: 0;
}

.el-radio-button >>> .el-radio-button__inner {
  border: solid #eee 0px !important;
  border-radius: 50px !important;
}

.order-by-container{
  margin: 30px 10px 0 10px;
}
</style>

MovieClassics.vue


<template>
<!--  经典影片-->
  <div>
    <div class="movie-list">
<!--      movie-item 是一个vue模板,用于实现放大的效果和电影列表的渲染-->
      <movie-item :movieItem="item" v-for="item in movieList" :key="item.movieId"></movie-item>
    </div>

    <div class="no-cinema" v-if="sorry">
      <p>抱歉,没有找到相关结果,请尝试用其他条件筛选。</p>
    </div>

    <div class="pageHelper">
      <el-pagination
          @current-change="handleCurrentChange"
          :current-page="pageNum"
          :page-size="pageSize"
          background
          layout="prev, pager, next"
          :total="total">
      </el-pagination>
    </div>
  </div>
</template>

<script>
import movieItem from "../../components/movie/movie-item";
import moment from "moment";

export default {
  name: "MovieClassics",
  components:{
    movieItem
  },
  props:{
    //接收到所要显示的电影类型
    movieCategoryId: Number,
    orderByColumn: String
  },
  data(){
    return{
      total: 0,
      pageSize: 30,
      pageNum: 1,
      movieList: [],
      sorry: false
    }
  },
  //computed的每一个计算属性都会被缓存起来,只要计算属性所依赖的属性发生变化,计算属性就会重新执行,视图也会更新
  computed: {
    listenChange () {
      const {movieCategoryId, orderByColumn} = this
      return {movieCategoryId, orderByColumn}
    }
  },
  created() {
    this.getMovieList()
  },
  watch:{
    //监听器
    listenChange(){
      this.getMovieList()
    }
  },
  methods: {
    async getMovieList(){
      let queryInfo = {
        movieCategoryId: this.movieCategoryId,
        orderByColumn: this.orderByColumn,
        pageSize: this.pageSize,
        pageNum: this.pageNum,
        isAsc: 'desc'
      }
      const { data : res } = await axios.get('sysMovie/find', {params: queryInfo})
      this.movieList = res.data
      this.total = res.total
      if(this.movieList.length === 0) this.sorry = true
      else this.sorry = false
    },
    handleCurrentChange(newPage) {
      this.pageNum = newPage
      this.getMovieList()
    }
  }
}
</script>

<style scoped>
.movie-list{
  display: flex;
  flex-wrap: wrap;
}

.pageHelper{
  display: flex;
  justify-content: center;
  margin: 40px 0px;
}

.no-cinema{
  display: flex;
  justify-content: center;
  margin-top: 40px;
  margin-bottom: 40px;
  font-size: 16px;
  color: #333;
}
</style>

movie-item.vue

<template>
  <!-- 一部电影 -->
  <div class="movie-item">
<!--     v-on:mouseover="isHover = true" 绑定鼠标的悬停和离开-->
    <div v-on:mouseover="isHover = true" v-on:mouseleave="isHover = false">
      <!-- 点击海报,进入该电影详细信息 -->
      <a :href="movieInfoUrl">
<!--      this.global.base  :const base = 'http://127.0.0.1:8181/'(后端的接口)
        movieItem.moviePoster:  /images/movie/2020/12/15/4425e22bc1264164a2fbdd01d56cd939.jpg   -->
        <img class="poster" :src="this.global.base + movieItem.moviePoster">
      </a>
      <!-- 鼠标划过时的效果 -->
      <div class="movie-item-hover" v-if="isHover">
        <!-- 海报 -->
        <a :href="movieInfoUrl">
          <img class="poster-hover" :src="this.global.base + movieItem.moviePoster">
          <!-- 鼠标划过时显示的信息 -->
          <div class="movie-hover-info">
            <div class="title-hover">
              <span class="name-tags">{{movieItem.movieName}}</span>
            </div>
            <div class="title-hover">
              <span class="name-tags">类型: </span>{{movieItem.movieCategoryList}}
            </div>
            <div class="title-hover">
              <span class="name-tags">上映时间: </span>{{movieItem.releaseDate}}
            </div>
          </div>
        </a>
      </div>
    </div>
<!--     显示电影下面的电影名字 -->
    <div class="title-style">
      <a href="/movieInfo">{{movieItem.movieName}}</a>
    </div>
  </div>
</template>

<script>
import moment from 'moment'
export default {
  name: "movie-item",
  props: {
    movieItem: Object
  },
  data() {
    return {
      isHover: false,
      movieInfoUrl: ''
    }
  },
  created(){
    this.movieItem.moviePoster = JSON.parse(this.movieItem.moviePoster)[0]
    this.movieItem.moviePictures = JSON.parse(this.movieItem.moviePictures)
    //解析上映的时间
    this.movieItem.releaseDate = moment(this.movieItem.releaseDate).format('YYYY-MM-DD')
    //类型之间加/
    this.movieItem.movieCategoryList = this.movieItem.movieCategoryList.map((obj,index) => {
      return obj.movieCategoryName;
    }).join("/")
    console.log(this.movieItem.movieCategoryList)
    //赋值目标链接
    this.movieInfoUrl = '/movieInfo/' + this.movieItem.movieId
  },

  //监听器
  watch: {
    'movieItem'() {

      // 监听 movieItem 属性的数据变化
      // 作用 : 只要 movieItem 的值发生变化,这个方法就会被调用

      this.movieItem.moviePoster = JSON.parse(this.movieItem.moviePoster)[0]
      this.movieItem.moviePictures = JSON.parse(this.movieItem.moviePictures)
      //  格式化时间
      this.movieItem.releaseDate = moment(this.movieItem.releaseDate).format('YYYY-MM-DD')
      //  在每个类型之间,添加/,为了美观
      this.movieItem.movieCategoryList = this.movieItem.movieCategoryList.map((obj,index) => {
        return obj.movieCategoryName;
      }).join("/")

      //赋值目标链接,用于跳转到这个电影的详细信息
      this.movieInfoUrl = '/movieInfo/' + this.movieItem.movieId
    }
  }
}
</script>

<style scoped>
.movie-item{
  margin-top: 30px;
  margin-left: 30px;
  display: inline-block;
  vertical-align: top;
  position: relative;
}

.poster{
  width: 160px;
  height: 220px;
}

.title-style{
  width: 160px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  text-align: center;
  font-size: 16px;
  color: #333;
  margin-top: 10px;
}

.score{
  color: #ffb400;
  font-size: 24px;
  font-style: italic;
}

a{
  text-decoration: none;
  color: #333;
}

.movie-item-hover{
  position: absolute;
  width: 218px;
  height: 300px;
  z-index: 10;
  top: -40px;
  left: -29px;
  overflow: hidden;
  background: #fff;
  box-shadow: 0 0 16px #fff, 0 0 6px rgba(0, 0, 0, 0.2);
}

.poster-hover{
  width: 218px;
  height: 300px;
}

.movie-hover-info{
  padding: 16px;
  height: 150px;
  box-sizing: border-box;
  position: absolute;
  z-index: 11;
  top: 150px;
  background: #fff;
  width: 218px;
  color: #999;
}

.title-hover:first-child{
  font-size: 20px;
  line-height: 20px;
  margin-top: 6px;
}

.title-hover{
  font-size: 16px;
  line-height: 16px;
  margin-top: 12px;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.name-tags{
  color: #333;
}
</style>

另外两个

在这里插入图片描述
这里只是请求的参数不一样,其余都是一样的。
以下为请求参数的对比:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

请求与响应

获得电影类别

在这里插入图片描述

{
  "msg": "操作成功",
  "total": 26,
  "code": 200,
  "data": [
    {
      "movieCategoryId": 1,
      "movieCategoryName": "爱情"
    },
    {
      "movieCategoryId": 2,
      "movieCategoryName": "喜剧"
    },
    {
      "movieCategoryId": 3,
      "movieCategoryName": "动画"
    },
    {
      "movieCategoryId": 4,
      "movieCategoryName": "剧情"
    },
    {
      "movieCategoryId": 5,
      "movieCategoryName": "恐怖"
    },
    {
      "movieCategoryId": 6,
      "movieCategoryName": "动作"
    },
    {
      "movieCategoryId": 7,
      "movieCategoryName": "科幻"
    },
    {
      "movieCategoryId": 8,
      "movieCategoryName": "悬疑"
    },
    {
      "movieCategoryId": 9,
      "movieCategoryName": "惊悚"
    },
    {
      "movieCategoryId": 10,
      "movieCategoryName": "犯罪"
    },
    {
      "movieCategoryId": 11,
      "movieCategoryName": "冒险"
    },
    {
      "movieCategoryId": 12,
      "movieCategoryName": "战争"
    },
    {
      "movieCategoryId": 13,
      "movieCategoryName": "奇幻"
    },
    {
      "movieCategoryId": 14,
      "movieCategoryName": "运动"
    },
    {
      "movieCategoryId": 15,
      "movieCategoryName": "家庭"
    },
    {
      "movieCategoryId": 16,
      "movieCategoryName": "古装"
    },
    {
      "movieCategoryId": 17,
      "movieCategoryName": "武侠"
    },
    {
      "movieCategoryId": 18,
      "movieCategoryName": "西部"
    },
    {
      "movieCategoryId": 19,
      "movieCategoryName": "历史"
    },
    {
      "movieCategoryId": 20,
      "movieCategoryName": "传记"
    },
    {
      "movieCategoryId": 21,
      "movieCategoryName": "歌舞"
    },
    {
      "movieCategoryId": 22,
      "movieCategoryName": "黑白电影"
    },
    {
      "movieCategoryId": 23,
      "movieCategoryName": "短片"
    },
    {
      "movieCategoryId": 24,
      "movieCategoryName": "纪录片"
    },
    {
      "movieCategoryId": 25,
      "movieCategoryName": "其他"
    },
    {
      "movieCategoryId": 26,
      "movieCategoryName": "历史"
    }
  ],
  "pageSize": 1000,
  "pageNum": 1
}

根据条件查询相应的电影

在这里插入图片描述
在这里插入图片描述

movie-item.vue

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汪程序猿

就当请我吃顿饭

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值