(09)首页开发——④ “热销推荐”和“周末去哪儿”组件 | Vue.js 项目实战: 移动端“旅游网站”开发

194 阅读10分钟
转载请注明出处,未经同意,不可修改文章内容。

🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。


1 需求

首页剩余两个简单的小组件:“热销推荐”组件和“周末去哪儿”组件,完成组件的布局和样式,然后渲染数据即可。

travel_09-01.gif

2 “热销推荐”组件

2.1 “热销推荐”的“结构与样式”

1️⃣首先在 home 目录下的 components 里新建“热销推荐”组件 Recommend.vuetravel09-02.png

<template>
  <div> <!-- 1️⃣-②:添加文字内容。 -->
    this is Recommend.
  </div>
</template>

<script>
export default {
  name: 'HomeRecommend' // 1️⃣-①:给组件命名为 HomeRecommend;
}
</script>

<style lang="stylus" scoped>
</style>

2️⃣打开 Home.vue ,在首页使用热销推荐组件 Recommend.vue

<template>
  <div>
    <home-header></home-header>
    <home-swiper></home-swiper>
    <home-icons></home-icons>

    <home-recommend></home-recommend> <!-- 2️⃣-③:在首页使用热销推荐组件。 -->
  </div>

</template>

<script>
import HomeHeader from './components/Header'
import HomeSwiper from './components/Swiper'
import HomeIcons from './components/Icons'

import HomeRecommend from './components/Recommend' /*
																									 2️⃣-①:从当前目录下的 components 
																									 中引入热销推荐组件 Recommend.vue;
                                                    */

export default {
  name: 'Home',
  components: {
    HomeHeader,
    HomeSwiper,
    HomeIcons,

    HomeRecommend /* 2️⃣-②:注册热销推荐组件; */
  }
}
</script>

<style>
</style>

保存后,返回页面查看,文字内容正常显示,控制台没有报错: travel09-03.png

接下来,我们对“热销推荐”进行分析: travel09-04.png

从上图可以看到,“热销推荐”下的内容,可以用“列表”来布局。其中的每一条内容,大致可分为两部分:左边为一个景点的图片区域,右边是对应的介绍区域,包含景点标题、介绍和一个按钮。

3️⃣打开 home 下 components 里的 Recommend.vue 编写代码:

<template>
  <div>
     <div class="title">热销推荐</div> <!-- 3️⃣-①:在最外层的 div 中,添加一个类名为 title 
																		 的 div ,内容为“热销推荐”; -->

     <ul> <!-- 3️⃣-②:添加一个列表,里边有一个类名为 item 的 li 标签,每一个 li 标签包含的内容
					为每一个“景点数据”; -->

       <li class="item"> <!-- 3️⃣-③:.item 里有一个 img 标签作为图片区域,
												 一个 div 作为介绍区域; -->

         <!-- 3️⃣-④:给 img 标签增加一个类名为 item-img; -->
         <img class="item-img" src="https://qdywxs.github.io/travel-images/recommendList01.jpg">

         <div class="item-info"> <!-- 3️⃣-⑤:给介绍区域增加一个类名 item-info; -->

           <p class="item-title">故宫</p> <!-- 3️⃣-⑥:.item-info 中用一个 p 标签显示
																				 “景点标题 .item-title”; -->
           
           <!-- 3️⃣-⑦:用一个 p 标签显示“景点描述 .item-desc”;-->
           <p class="item-desc">东方宫殿建筑代表,世界宫殿建筑典范</p>

           <button class="item-button">查看详情</button> <!-- 3️⃣-⑧:添加一个“查看详情”按钮,
																											 增加类名为 item-button。 -->

         </div>
       </li>
     </ul>

  </div>
</template>

<script>
export default {
  name: 'HomeRecommend'
}
</script>

<style lang="stylus" scoped>
</style>

保存后,返回页面查看结构,再与原稿进行对比观察: travel09-05.png

4️⃣结构没有问题,返回 Recommend.vue 继续编写样式:

<template>
  <div>
     <div class="title">热销推荐</div>
     <ul>
       
      <!-- 4️⃣-⑧:由于我们引入过解决一像素边框问题的“border.css”,所以要添加一像素的分隔线,
			直接在 li 标签添加一个 border-bottom 的类名即可。 -->
       <li class="item border-bottom">
         
         <img class="item-img" src="https://qdywxs.github.io/travel-images/recommendList01.jpg">
         <div class="item-info">
           <p class="item-title">故宫</p>
           <p class="item-desc">东方宫殿建筑代表,世界宫殿建筑典范</p>
           <button class="item-button">查看详情</button>
         </div>
       </li>
     </ul>
  </div>
</template>

<script>
export default {
  name: 'HomeRecommend'
}
</script>

<style lang="stylus" scoped>
.title /*
  		 4️⃣-①:设置 .title 的 margin-top 为 0.2rem,背景色为 #eee,高度为 0.8rem,
  		 文本缩进 0.2rem;
   			*/
  margin-top: .2rem
  background: #eee
  line-height: .8rem
  text-indent: .2rem

.item /* 4️⃣-②:设置 .item 内容溢出时隐藏,使用 flex 布局,高度为 1.9rem; */
  overflow: hidden
  display: flex
  height: 1.9rem

  .item-img /* 4️⃣-③:设置图片宽、高为 1.7rem,padding 为 0.1rem; */
    width: 1.7rem
    height: 1.7rem
    padding: .1rem

  .item-info /* 4️⃣-④:设置景点介绍区域的 flex 值为 1,并添加 0.1rem 的 padding; */
    flex: 1
    padding: .1rem

    .item-title /* 4️⃣-⑤:设置景点标题的行高为 0.54rem,字体大小为 0.32rem; */
      line-height: .54rem
      font-size: .32rem

    .item-desc /* 4️⃣-⑥:设置景点描述的行高为 0.4rem,字体颜色为 #ccc; */
      line-height: .4rem
      color: #ccc

    .item-button /*
  							 4️⃣-⑦:设置按钮距离上方元素 0.16rem,行高 0.44rem,字体颜色为白色,
  							 背景色为橙色,左、右 padding 为 0.2rem,添加 0.06rem 的圆角;
   								*/
      margin-top: .16rem
      line-height: .44rem
      color: #fff
      background: #ff9300
      padding: 0 .2rem
      border-radius: .06rem
</style>

保存后,返回页面查看效果。在景点介绍区域中,有景点标题和描述两个区域的字数不确定,所以这两个位置我们都可以添加一个“文字溢出加点”的效果: travel09-06.png

5️⃣在 Recommend.vue 的样式中使用 mixins.styl

<template>
  <div>
     <div class="title">热销推荐</div>
     <ul>
       <li class="item border-bottom">
         <img class="item-img" src="https://qdywxs.github.io/travel-images/recommendList01.jpg">
         <div class="item-info">
           <p class="item-title">故宫</p>
           <p class="item-desc">东方宫殿建筑代表,世界宫殿建筑典范</p>
           <button class="item-button">查看详情</button>
         </div>
       </li>
     </ul>
  </div>
</template>

<script>
export default {
  name: 'HomeRecommend'
}
</script>

<style lang="stylus" scoped>
  
/* 5️⃣-①:引入 mixins.styl 文件; */
@import '~styles/mixins.styl'
  
.title
  margin-top: .2rem
  background: #eee
  line-height: .8rem
  text-indent: .2rem
.item
  overflow: hidden
  display: flex
  height: 1.9rem
  .item-img
    width: 1.7rem
    height: 1.7rem
    padding: .1rem
  .item-info
    flex: 1
    padding: .1rem

    .item-title /* 5️⃣-②:给景点标题和描述添加 ellipsis 方法。 */
      line-height: .54rem
      font-size: .32rem
      ellipsis()
    .item-desc
      line-height: .4rem
      color: #ccc
      ellipsis()

    .item-button
      margin-top: .16rem
      line-height: .44rem
      color: #fff
      background: #ff9300
      padding: 0 .2rem
      border-radius: .06rem
</style>

❌保存后,返回页面进行测试,发现当文字超出时,没有出现预期的“点” travel09-07.png

❓这里如何让文字溢出加点?
答:有一个小技巧,就是给它们的父元素添加“最小宽度”。

<template>
  <div>
     <div class="title">热销推荐</div>
     <ul>
       <li class="item border-bottom">
         <img class="item-img" src="https://qdywxs.github.io/travel-images/recommendList01.jpg">
         <div class="item-info">
           <p class="item-title">故宫</p>
           <p class="item-desc">东方宫殿建筑代表,世界宫殿建筑典范</p>
           <button class="item-button">查看详情</button>
         </div>
       </li>
     </ul>
  </div>
</template>

<script>
export default {
  name: 'HomeRecommend'
}
</script>

<style lang="stylus" scoped>
@import '~styles/mixins.styl'
.title
  margin-top: .2rem
  background: #eee
  line-height: .8rem
  text-indent: .2rem
.item
  overflow: hidden
  display: flex
  height: 1.9rem
  .item-img
    width: 1.7rem
    height: 1.7rem
    padding: .1rem

  .item-info /* ❗️给 .item-info 添加最小宽度。 */
    flex: 1
    padding: .1rem
    min-width: 0

    .item-title
      line-height: .54rem
      font-size: .32rem
      ellipsis()
    .item-desc
      line-height: .4rem
      color: #ccc
      ellipsis()
    .item-button
      margin-top: .16rem
      line-height: .44rem
      color: #fff
      background: #ff9300
      padding: 0 .2rem
      border-radius: .06rem
</style>

保存后,返回页面查看,当文字超出时,正确显示出了 ...travel09-08.png

2.2 “热销推荐”的“数据渲染”

完成了热销推荐组件结构与样式的编写后,我们就需要把获取到的数据渲染在页面上。这里,我们依然模拟真实数据来进行。

开始之前,先回忆一下,我们目前想要在页面渲染数据的整个步骤:

  1. 在小组件的 data 函数中返回出数据项;
  2. 使用 v-for 指令对数据进行循环;
  3. 使用模板语法在页面上渲染数据。

6️⃣热销推荐组件的数据定义为 recommendList

<template>
  <div>
     <div class="title">热销推荐</div>
     <ul>
      <!-- 6️⃣-②:在 li 标签上循环 recommendList 数组中的每一项,并绑定 key 值为循环项的 id; -->
       <li class="item border-bottom" v-for="item of recommendList" :key="item.id">

         <img class="item-img" :src="item.imgUrl"> <!-- 6️⃣-③:绑定图片地址为循环项的
																									 imgUrl; -->

         <div class="item-info">
           <p class="item-title">{{item.title}}</p> <!-- 6️⃣-④:绑定景点标题为循环项的
																										title; -->

           <p class="item-desc">{{item.desc}}</p> <!-- 6️⃣-⑤:绑定景点描述为循环项的
																									desc; -->

           <button class="item-button">查看详情</button>
         </div>
       </li>
     </ul>
  </div>
</template>

<script>
export default {
  name: 'HomeRecommend',

  data () { /*
  					6️⃣-①:在组件的 data 函数中,返回 recommendList 数组(数组中的每个对象,分别包含
  					对应的 id、景点配图链接、经典标题、景点描述);
             */
    return {
      recommendList: [{
        id: '0001',
        imgUrl: 'https://qdywxs.github.io/travel-images/recommendList01.jpg',
        title: '故宫',
        desc: '东方宫殿建筑代表,世界宫殿建筑典范'
      }, {
        id: '0002',
        imgUrl: 'https://qdywxs.github.io/travel-images/recommendList02.jpg',
        title: '南山滑雪场',
        desc: '北京专业级滑雪圣地'
      }, {
        id: '0003',
        imgUrl: 'https://qdywxs.github.io/travel-images/recommendList03.jpg',
        title: '天安门广场',
        desc: '我爱北京天安门,天安门上太阳升'
      }, {
        id: '0004',
        imgUrl: 'https://qdywxs.github.io/travel-images/recommendList04.jpg',
        title: '水立方',
        desc: '中国的荣耀,阳光下的晶莹水滴'
      }, {
        id: '0005',
        imgUrl: 'https://qdywxs.github.io/travel-images/recommendList05.jpg',
        title: '温都水城养生馆',
        desc: '各种亚热带植物掩映其间,仿佛置身热带雨林'
      }]
    }
  }
}
</script>

<style lang="stylus" scoped>
@import '~styles/mixins.styl'
.title
  margin-top: .2rem
  background: #eee
  line-height: .8rem
  text-indent: .2rem
.item
  overflow: hidden
  display: flex
  height: 1.9rem
  .item-img
    width: 1.7rem
    height: 1.7rem
    padding: .1rem
  .item-info
    flex: 1
    padding: .1rem
    min-width: 0
    .item-title
      line-height: .54rem
      font-size: .32rem
      ellipsis()
    .item-desc
      line-height: .4rem
      color: #ccc
      ellipsis()
    .item-button
      margin-top: .16rem
      line-height: .44rem
      color: #fff
      background: #ff9300
      padding: 0 .2rem
      border-radius: .06rem
</style>

保存后,返回页面查看,没有报错,页面内容没有问题: travel09-09.png

3 “周末去哪儿”组件

3.1 “周末去哪儿”的结构与样式

“周末去哪儿”组件与“热销推荐”组件结构类似,样式也更为简单: travel09-10.png

7️⃣在 home 下的 components 中,新建“周末去哪儿”组件 Weekend.vue

<template>
  <div> <!-- 7️⃣-②:添加文字内容。 -->
    this is Weekend.
  </div>
</template>

<script>
export default {
  name: 'HomeWeekend' // 7️⃣-①:给组件命名为 HomeWeekend;
}
</script>

<style lang="stylus" scoped>
</style>

8️⃣在首页 Home.vue 中使用小组件 Weekend.vue

<template>
  <div>
    <home-header></home-header>
    <home-swiper></home-swiper>
    <home-icons></home-icons>
    <home-recommend></home-recommend>

    <home-weekend></home-weekend>  <!-- 8️⃣-③:在首页使用“周末去哪儿”组件。 -->
  </div>

</template>

<script>
import HomeHeader from './components/Header'
import HomeSwiper from './components/Swiper'
import HomeIcons from './components/Icons'
import HomeRecommend from './components/Recommend'

import HomeWeekend from './components/Weekend' /*
																							 8️⃣-①:从当前目录下的 components
                                               中引入“周末去哪儿”组件 Weekend.vue;
                                                */

export default {
  name: 'Home',
  components: {
    HomeHeader,
    HomeSwiper,
    HomeIcons,
    HomeRecommend,
    HomeWeekend /* 8️⃣-②:注册“周末去哪儿”组件; */
  }
}
</script>

<style>
</style>

保存后,返回页面查看,文字内容正确显示,且没有报错: travel09-11.png

9️⃣返回 Weekend.vue 编写结构与样式:

<template>
  <div>
    <div class="title">周末去哪儿</div> <!-- 9️⃣-①:在最外层的 div 中,添加一个类名为 title
                                     的 div ,内容为“周末去哪儿”; -->

    <ul> <!-- 9️⃣-②:添加一个列表,里边有一个类名为 item 的 li 标签,每一个 li 标签包含的内容
         为每一个“景点数据”; -->

      <li class="item border-bottom"> <!-- 9️⃣-③:li 标签里边有两个 div,一个为图片区域,
																			一个景点为介绍区域;给 li 标签添加类名 border-bottom
																			增加分隔线; -->

        <div class="item-img-wrapper"> <!-- 9️⃣-④:.item-img-wrapper 作为容器包裹图片; -->
          
          <img class="item-img" src="https://qdywxs.github.io/travel-images/weekendList01.jpg">
        </div>

        <div class="item-info"> <!-- 9️⃣-⑤:.item-info 为景点介绍区域,包含两个 p 标签,
																分别为景点标题和景点描述; -->
          <p class="item-title">北京温泉排行榜</p>
          <p class="item-desc">细数北京温泉,温暖你的冬天</p>
        </div>

      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HomeWeekend'
}
</script>

<style lang="stylus" scoped>

/* 9️⃣-⑩:引入 mixins.styl 文件; */
@import '~styles/mixins.styl'

.title /* 9️⃣-⑥:设置 .title 的背景色为 #eee,行高为 0.8rem,文本缩进 0.2rem; */
  background: #eee
  line-height: .8rem
  text-indent: .2rem

.item-img-wrapper /* 9️⃣-⑦:设置图片的容器宽高比为图片的宽高比,作为占位区域防止内容抖动; */
  overflow: hidden
  height: 0
  padding-bottom: 38%

  .item-img /* 9️⃣-⑧:设置图片宽度为 100%; */
    width: 100%

.item-info /* 9️⃣-⑨:设置景点介绍区域 padding 为 0.1rem; */
  padding: .1rem

  .item-title /* 9️⃣-⑪:设置景点标题行高为 0.54rem,字体大小为 0.32rem,调用 ellipsis 方法; */
    line-height: .54rem
    font-size: .32rem
    ellipsis()

  .item-desc /* 9️⃣-⑫:设置景点描述行高为 0.4rem,字体颜色为 #ccc,调用 ellipsis 方法; */
    line-height: .4rem
    color: #ccc
    ellipsis()
</style>

保存后,返回页面查看,控制台无报错,页面显示正常: travel09-12.png

3.2 “周末去哪儿”的数据渲染

🔟完成了 Weekend.vue 的结构与样式后,我们就可以将数据渲染到页面上:

<template>
  <div>
    <div class="title">周末去哪儿</div>
    <ul>

      <!-- 🔟-②:循环 weekendList 数组中的每一项,并绑定 key 值为循环项的 id; -->
      <li class="item border-bottom" v-for="item of weekendList" :key="item.id">
        <div class="item-img-wrapper">

          <img class="item-img" :src="item.imgUrl"> <!-- 🔟-③:绑定图片链接为循环项的
																										imgUrl; -->

        </div>
        <div class="item-info">

          <p class="item-title">{{item.title}}</p> <!-- 🔟-④:渲染景点标题为循环项的
																									 title; -->

          <p class="item-desc">{{item.desc}}</p> <!-- 🔟-⑤:渲染景点描述为循环项的
																								 desc;-->
          
        </div>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HomeWeekend',

  data () { /* 🔟-①:在 data 中返回“周末去哪儿”的数据 weekendList;*/
    return {
      weekendList: [{
        id: '0001',
        imgUrl: 'https://qdywxs.github.io/travel-images/weekendList01.jpg',
        title: '北京温泉排行榜',
        desc: '细数北京温泉,温暖你的冬天'
      }, {
        id: '0002',
        imgUrl: 'https://qdywxs.github.io/travel-images/weekendList02.jpg',
        title: '北京必游TOP10',
        desc: '来北京必去的景点非这些地方莫属'
      }, {
        id: '0003',
        imgUrl: 'https://qdywxs.github.io/travel-images/weekendList03.jpg',
        title: '寻找北京的皇城范儿',
        desc: '数百年的宫廷庙宇,至今依旧威严霸气'
      }, {
        id: '0004',
        imgUrl: 'https://qdywxs.github.io/travel-images/weekendList04.jpg',
        title: '学生最爱的博物馆',
        desc: '周末干嘛?北京很多博物馆已经免费开放啦'
      }, {
        id: '0005',
        imgUrl: 'https://qdywxs.github.io/travel-images/weekendList05.jpg',
        title: '儿童剧场,孩子的乐园',
        desc: '带宝贝观看演出,近距离体验艺术的无穷魅力'
      }]
    }
  }
}
</script>

<style lang="stylus" scoped>
@import '~styles/mixins.styl'
.title
  background: #eee
  line-height: .8rem
  text-indent: .2rem
.item-img-wrapper
  overflow: hidden
  height: 0
  padding-bottom: 38%
  .item-img
    width: 100%
.item-info
  padding: .1rem
  .item-title
    line-height: .54rem
    font-size: .32rem
    ellipsis()
  .item-desc
    line-height: .4rem
    color: #ccc
    ellipsis()
</style>

保存后,返回页面查看,控制台无报错,页面内容显示正确:

travel_09-13.gif

以上,就完成了首页剩余的“热销推荐”和“周末去哪儿”两个小组件。

但,我们首页中每个组件里的内容,都是直接定义在 data 里边固定的数据。在下一篇中,我们将会利用第三方模块 axios 发送 Ajax 请求,动态获取首页数据。

祝好,qdywxs ♥ you!