zoukankan      html  css  js  c++  java
  • 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;
         .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

  • 相关阅读:
    2016年回家的大概经过
    [转载][记录]shell 批量修改文件名
    Tinymce4 中Ajax多次加载时,会出现菜单在第二次进入时,显示的下拉菜单在左上角
    PHP生成HTML页面顶部出现空白部分(&#65279字符?)
    tcpdf MultiCell line break
    [转载][记录]javascript生成不重复的随机数
    [转载]PHP 字符串替换中文
    PHP 使用get_class_methods()和array_diff() 兩個相同的類中方法差集
    mysql datetime 排序
    highcharts 去掉右下角链接
  • 原文地址:https://www.cnblogs.com/donghaoblogs/p/10452480.html
Copyright © 2011-2022 走看看