Vue仿卖座电影开发纪实(四)

182 阅读1分钟

抽离电影条目子组件FilmItem

定义子组件

  • 创建文件src/components/film/FilmItem.vue
  • 从正在热映列表中拷贝电影条目的模板与样式到FilmItem.vue

src/components/film/FilmItem.vue

<template>
  <li>
    <div class="left">
      <img :src="item.poster" alt="" />
    </div>

    <div class="middle">
      <p>
        <span class="name">{{ item.name }}</span>
        <span class="dimension">{{ item.item.name }}</span>
      </p>
      <p>
        观众评分
        <span class="grade">{{ item.grade }}</span>
      </p>
      <p>
        <span class="actors">
          主演:{{ item.actors.map((actor) => actor.name).join(" ") }}
        </span>
      </p>
      <p>{{ item.nation }} | {{ item.runtime }}分钟</p>
    </div>

    <div class="right">
      <button class="ticket">购票</button>
    </div>
  </li>
</template>

<script>
export default {};
</script>

<style lang="scss" scoped>
@import "@assets/variable.scss";

li {
  display: flex;
  border-bottom: 1px solid #eee;
  padding: 10px;
  font-size: 13px;
  color: #888;

  .left {
    display: flex;
    justify-content: center;
    align-items: center;
    img {
      width: 66px;
    }
  }

  .middle {
    display: flex;
    flex-direction: column;
    justify-content: center;

    flex-grow: 1;
    margin-left: 10px;

    p {
      margin-bottom: 2px;
    }

    span.name {
      font-size: 16px;
      color: #333;
    }

    span.dimension {
      background-color: #ccc;
      color: white;
      border-radius: 2px;
      margin-left: 5px;
      padding: 0 2px;
      font-size: 12px;
    }

    span.grade {
      color: $myOrange;
    }

    span.actors {
      display: inline-block;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      width: 14rem;
    }
  }

  .right {
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 10px;

    button {
      width: 50px;
      background-color: white;
      color: $myOrange;
      border: 1px solid $myOrange;
      padding: 3px 5px;
      border-radius: 2px;
      font-size: 13px;
    }
  }
}
</style>
  • FilmItem子组件需要渲染的电影数据item以props的形式由父组件注入
<script>
export default {
    /* 定义父组件注入的props */
    props:["item"]
};
</script>
  • 父组件【热映列表/NowPlaying】不再渲染一堆li,取而代之的是渲染一堆FilmItem子组件
<ul v-else>

  <!-- :item="film" 将电影列表中的每个film作为数据项item注入给子组件 -->
  <FilmItem
    v-for="film in films"
    :key="film.filmId"
    :item="film"
  ></FilmItem>
</ul>

同时父组件需要声明子组件

// 引入FilmItem子组件
import FilmItem from "./FilmItem.vue";

/* 对外导出组件实例 */
export default {
  /* 注册子组件 */
  components: {
    FilmItem,
  },
  ...
}

优化tabbar

切换tab时tab图标不能点亮

  • tab图标位于span下的i
  • 当tab点击时 router-link组件会加载一个active样式
  <RouterLink active-class="active" class="tab" to="/film">
    <span><i class="fa fa-toggle-right"></i></span>
    <span>电影</span>
  </RouterLink>
  • 在样式中给.tab.active>span>i以样式
.tab.active > span,
.tab.active > span > i {
  color: #ff5f16;
}

切换到【电影】tab时默认选中【正在热映】

  • 在路由表中配置重定向,当地址栏path为/film时直接重定向到/film/nowPlaying
  • 注意:路由表是从上向下解析的,所以这个重定向应配置在正常的/film路由之前
{
  path: "/film",
  redirect: "/film/nowPlaying",
},

无论选中【正在热映】还是【即将上映】都点亮【电影】tab

  • vue-router插件给所有组件实例都绑定了$route,用于组件实时获取当前的路由信息
  • this.$route.path即为当前的实时路由地址
  • 我们给【电影】的router-link组件加一个动态判断的class名曰active
  • 当实时路由以/film/开头时,active样式添加到电影的router-link,否则移除 -:class="{active:$route.path.startsWith('/film/')}"
  • 一旦active样式作用在router-link上,该tab就被点亮了
  <RouterLink 
  active-class="active" 
  class="tab" 
  :class="{active:$route.path.startsWith('/film/')}" 
  to="/film"
  >
    <span><i class="fa fa-toggle-right"></i></span>
    <span>电影</span>
  </RouterLink>