Vue2.5开发去哪儿网App 详情页面开发

一,banner 图的设计

1. 新建detail的路由

 

import Detail from '@/pages/detail/Detail'
......    
{
      path: '/detail',
      name: 'Detail',
      component: Detail
    }

 

Detail.vue

<template>
  <div>
    <detail-banner></detail-banner>
  </div>
</template>

<script>
import DetailBanner from './components/Banner'
export default {
  name: 'Detail',
  components: {
    DetailBanner
  }
}
</script>

<style>

</style>
View Code

新建 Banner.vue组件

<template>
  <div class="banner">
    <img src="http://img1.qunarzz.com/sight/p0/1409/19/adca619faaab0898245dc4ec482b5722.jpg_600x330_f922b488.jpg"
         class="banner-img" alt="">
    <div class="banner-info">
      <div class="banner-title">故宫(AAAAA景区)</div>
      <div class="banner-number"><span class="iconfont banner-icon">&#xe6bc;</span>39</div>
    </div>
  </div>
</template>

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

<style lang="stylus" scoped>
  .banner
    position relative
    overflow hidden
    height 0
    padding-bottom 55%
    .banner-img
      width 100%
    .banner-info
      position absolute
      color #ffffff
      left 0
      right 0
      bottom 0
      line-height .6rem
      background-image linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,0.8))
      display flex
      .banner-title
        font-size .32rem
        padding 0 .2rem
        flex 1
      .banner-number
        margin .14rem
        padding 0 .3rem
        line-height .4rem
        height .32rem
        font-size .24rem
        border-radius .2rem
        background rgba(0, 0, 0, 8)
        .banner-icon
          font-size .24rem
          padding .02rem
</style>
View Code

二,公用图片画廊组件

1. 创建一个公用组件 Gallary.vue

使用  vue-awesome-swiper 完成图片滚动

<template>
  <div class="container" @click="HandleClick">
    <div class="wrapper">
      <swiper :options="swiperOption">
        <!-- slides -->
        <swiper-slide v-for="(item,index) in imgs" :key="index">
          <img class="gallery-img" :src="item" alt="">
        </swiper-slide>
        <!-- Optional controls -->
        <div class="swiper-pagination"  slot="pagination"></div>
      </swiper>
    </div>
  </div>
</template>

<script>
export default {
  name: 'CommonGallary',
  props: {
    imgs: {
      type: Array
    }
  },
  methods: {
    HandleClick () {
      // 关闭
      this.$emit('close')
    }
  },
  data () {
    return {
      swiperOption: {
        loop: true,
        pagination: '.swiper-pagination',
        paginationType: 'fraction',
        // observer启动动态检查器(OB/观众/观看者),当改变swiper的样式(例如隐藏/显示)或者修改swiper的子元素时,自动初始化swiper。
        // 默认false
        observer: true,
        observeParents: true
      }
    }
  }
}
</script>

<style lang="stylus" scoped>
  .container >>> .swiper-container
    overflow inherit
  .container
    display flex
    flex-direction column
    justify-content: center
    background-color #000
    position fixed
    top 0
    left 0
    right 0
    bottom 0
    z-index 999
    .wrapper
      padding-bottom 100%
      height 0
      width 100%
      .gallery-img
        width 100%
      .swiper-pagination
        color #fff
        bottom -1rem
</style>
View Code

2. Banner.vue

定义变量   showGallary 负责照片墙的显示与否

<common-gallary @close="HandleClose" :imgs="imgs" v-show="showGallary"></common-gallary>
监听变化,传入图片数据,显示与否
<template>
  <div>
    <div class="banner">
      <img v-show="!showGallary" @click="handleImgClick" src="http://img1.qunarzz.com/sight/p0/1409/19/adca619faaab0898245dc4ec482b5722.jpg_600x330_f922b488.jpg"
           class="banner-img" alt="">
      <div class="banner-info">
        <div class="banner-title">故宫(AAAAA景区)</div>
        <div class="banner-number"><span class="iconfont banner-icon">&#xe6bc;</span>39</div>
      </div>
    </div>
    <common-gallary @close="HandleClose" :imgs="imgs" v-show="showGallary"></common-gallary>
  </div>
</template>

<script>
import CommonGallary from 'common/gallary/Gallary'
export default {
  name: 'DetailBanner',
  data () {
    return {
      imgs: [
        'http://img1.qunarzz.com/sight/p0/1510/8e/8eea8eb6f41698290.img.jpg_r_800x800_83a5fe3a.jpg',
        'http://img1.qunarzz.com/sight/p0/1510/ca/ca60a080020329ef90.img.jpg_350x240_9ff2208e.jpg',
        'http://img1.qunarzz.com/sight/p0/1510/cc/ccafbdaac21bdbf790.img.jpg_350x240_c35f8451.jpg'
      ],
      showGallary: false
    }
  },
  methods: {
    handleImgClick () {
      this.showGallary = true
    },
    HandleClose () {
      this.showGallary = false
    }
  },
  components: {
    CommonGallary
  }
}
</script>

<style lang="stylus" scoped>
  .banner
    position relative
    overflow hidden
    height 0
    padding-bottom 55%
    .banner-img
      width 100%
    .banner-info
      position absolute
      color #ffffff
      left 0
      right 0
      bottom 0
      line-height .6rem
      background-image linear-gradient(top,rgba(0,0,0,0),rgba(0,0,0,0.8))
      display flex
      .banner-title
        font-size .32rem
        padding 0 .2rem
        flex 1
      .banner-number
        margin .14rem
        padding 0 .3rem
        line-height .4rem
        height .32rem
        font-size .24rem
        border-radius .2rem
        background rgba(0, 0, 0, 8)
        .banner-icon
          font-size .24rem
          padding .02rem
</style>
View Code

 

 

三,header 渐隐渐现效果

后退符号制作:

 

    <router-link tag="div" to="/" class="header-abs">
      <div class="iconfont back-icon header-abs-back">&#xe606;</div>
    </router-link>

 

显示详情:

    <div class="header-fixed" v-show="!showAbs">
      <router-link to="/">
        <div class="iconfont back-icon header-fixed-back">&#xe606;</div>
      </router-link>
      景点详情
    </div>

 

当下滑一定距离,header-fixed 显示出来

添加绑定滚动事件

  methods: {
    handleScroll () {
      console.log(document.documentElement.scrollTop)
    }
  },
  activated () {
    window.addEventListener('scroll', this.handleScroll)
  }

 

当滚动> 60 时,显示出来

    handleScroll () {
      const top = document.documentElement.scrollTop
      if (top > 60) {
        this.showAbs = false
      } else {
        this.showAbs = true
      }
    }

渐隐渐现制作:

opacityStyle // 渐隐渐现变量
给header-fixed绑定 :style="opacityStyle"
handleScroll () {
      const top = document.documentElement.scrollTop
      if (top > 60) {
        let opacity = top / 140
        opacity = opacity > 1 ? 1 : opacity
        this.opacityStyle = { opacity }
        this.showAbs = false
      } else {
        this.showAbs = true
      }
    }

<template>
  <div>
    <router-link v-show="showAbs" tag="div" to="/" class="header-abs">
      <div class="iconfont back-icon header-abs-back">&#xe606;</div>
    </router-link>
    <div class="header-fixed" v-show="!showAbs"  :style="opacityStyle">
      <router-link to="/">
        <div class="iconfont back-icon header-fixed-back">&#xe606;</div>
      </router-link>
      景点详情
    </div>
  </div>
</template>

<script>
export default {
  name: 'DetailHeader',
  data () {
    return {
      showAbs: true,
      opacityStyle: {
        opacity: 0
      }
    }
  },
  methods: {
    handleScroll () {
      const top = document.documentElement.scrollTop
      if (top > 60) {
        let opacity = top / 140
        opacity = opacity > 1 ? 1 : opacity
        this.opacityStyle = { opacity }
        this.showAbs = false
      } else {
        this.showAbs = true
      }
    }
  },
  activated () {
    window.addEventListener('scroll', this.handleScroll)
  }
}
</script>

<style lang="stylus" scoped>
  @import "~styles/varibles.styl"
  .header-abs
    position: absolute
    left .2rem
    top .2rem
    width .8rem
    height .8rem
    line-height .8rem
    border-radius .4rem
    text-align center
    background rgba(0,0,0,.8)
    .header-abs-back
      color #ffffff
      font-size .4rem
  .header-fixed
    position fixed
    top 0
    left 0
    right 0
    overflow hidden
    height $headerHeight
    line-height $headerHeight
    color #ffffff
    background $bgColor
    text-align center
    font-size .32rem
    .header-fixed-back
      color #ffffff
      position absolute
      top 0
      left 0
      width .64rem
</style>
Header.vue

四,对全局事件解绑

因为绑定了  window.addEventListener(......)

对其他组件也产生影响

  activated () {
    window.addEventListener('scroll', this.handleScroll)
  },
  // 解绑 deactivated () { window.removeEventListener(
'scroll', this.handleScroll) }
生命周期函数:
activated
  keep-alive组件激活时调用。
  该钩子在服务器端渲染期间不被调用。
deactivated
  keep-alive组件停用时调用。
  该钩子在服务端渲染期间不被调用

 

五,递归组件实现详情页列表

例如有以下数据:

      list: [
        {
          title: '成人票',
          children: [
            {
              title: '特惠双人票'
            },
            {
              title: '三人票',
              children: [
                {
                  title: '包午餐三人票'
                }
              ]
            }
          ]
        },
        {
          title: '学生票',
          children: [
            {
              title: '学生票七日游'
            }
          ]
        },
        {
          title: '儿童票'
        },
        {
          title: '特惠票'
        }
      ]

新建LIst.vue

   <div class="item" v-for="(item,index) in list" :key="index">
     <div class="item-title border-bottom">
       <span class="item-title-icon"></span>
       {{item.title}}
     </div>
     <div v-if="item.children" class="children">
// 多层遍历 <detail-list :list="item.children"></detail-list> </div> </div>
<template>
  <div>
   <div class="item" v-for="(item,index) in list" :key="index">
     <div class="item-title border-bottom">
       <span class="item-title-icon"></span>
       {{item.title}}
     </div>
     <div v-if="item.children" class="children">
       <detail-list :list="item.children"></detail-list>
     </div>
   </div>
  </div>
</template>

<script>
export default {
  name: 'DetailList',
  props: {
    list: Array
  }
}
</script>

<style lang="stylus" scoped>
  .item-title
    line-height .8rem
    font-size .32rem
    padding 0 .2rem
  .item-title-icon
    display: inline-block;
    width: .36rem;
    height: .36rem;
    background: url(http://s.qunarzz.com/piao/image/touch/sight/detail.png) 0 -.45rem no-repeat;
    margin-right: .1rem;
    background-size: .4rem 3rem
    position relative
    left .06rem
    top: .06rem
  .children
    padding 0 .5rem
</style>
List.vue

 

posted @ 2019-02-28 18:53  最美的烟火  阅读(1178)  评论(2编辑  收藏  举报