Vue2.5 旅游项目实例19 详情页 动态路由及banner布局

创建分支:detail-banner

拉取到本地并切换分支:

git pull
git checkout detail-banner

打开home下的Recommend.vue文件:

<router-link tag="li" class="item border-bottom"
     :to="'/detail/' + item.id"
     v-for="item in recommendList" :key="item.id">
      <img class="item-img" :src="item.imgUrl" alt="" />
      <div class="item-info">
        <p class="item-title">{{item.title}}</p>
        <p class="item-desc">{{item.desc}}</p>
        <button class="item-button">查看详情</button>
      </div>
</router-link>

然后新建detail文件夹下的Dettail.vue文件,并创建路由:

import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/pages/home/Home'
import City from '@/pages/city/City'
import Detail from '@/pages/detail/Detail'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/city',
      name: 'City',
      component: City
    },
    {
      path: '/detail/:id',
      name: 'Detail',
      component: Detail
    }
  ]
})

在detail目录下创建components文件夹,新建Banner.vue文件:

<template>
<div>
  banner
</div>
</template>

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

<style lang="stylus" scoped>

</style>

然后在Detail.vue中引用banner组件:

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

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

继续编辑Banner.vue文件:

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

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

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

效果图:

然后我们想要的效果是,点击顶部banner的时候,弹出一个画廊组件,这个组件里可以实现图片的轮播,图片下面还有当前图片的页码。

公用图片画廊组件拆分

在src目录下创建common文件夹,里面存放一些全局公用的组件。

在common目录下创建gallary文件夹,新建Gallary.vue文件:

<template>
<div>gallary</div>
</template>

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

<style lang="stylus" scoped>

</style>

然后打开build目录下的webpack.base.conf.js文件,添加一个别名:

resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      'styles': resolve('src/assets/styles'),
      'common': resolve('src/common'),
    }
},

保存后,记得重启服务。

继续打开Banner.vue文件,引用gallary组件:

<template>
<div>
  <div class="banner">
    <img class="banner-img" src="//img1.qunarzz.com/sight/p0/1409/19/adca619faaab0898245dc4ec482b5722.jpg_600x330_f922b488.jpg" />
    <div class="banner-info">
      <div class="banner-title">故宫(AAAAA景区)</div>
      <div class="banner-number"><i class="iconfont banner-icon">&#xe692;</i> 12</div>
    </div>
  </div>
  <common-gallary></common-gallary>
</div>
</template>

<script>
import CommonGallary from 'common/gallary/Gallary'
export default {
  name: 'DetailBanner',
  components: {
    CommonGallary
  }
}
</script>

然后就要继续编写Gallary.vue文件:

先写死图片看效果:

<template>
<div class="container">
  <div class="wrapper">
    <swiper :options="swiperOptions">
      <swiper-slide >
        <img width="100%" src="http://img1.qunarzz.com/sight/p0/1409/19/adca619faaab0898245dc4ec482b5722.jpg_r_800x800_6edd8174.jpg" />
      </swiper-slide>
      <swiper-slide >
        <img width="100%" src="http://img1.qunarzz.com/sight/p0/1907/ca/ca68bd95bc36bdba3.img.jpg_r_800x800_33169c4b.jpg" />
      </swiper-slide>
      <div class="swiper-pagination"  slot="pagination"></div>
    </swiper>
  </div>
</div>
</template>

<script>
export default {
  name: 'CommonGallary',
  data () {
    return {
      swiperOptions: {
        pagination: '.swiper-pagination'
      }
    }
  }
}
</script>

<style lang="stylus" scoped>
.container
  display:flex
  flex-direction:column
  justify-content:center
  z-index: 99
  position: fixed
  left:0
  right:0
  top:0
  bottom:0
  background: #000
  .wrapper
     100%
    height: 0
    padding-bottom: 66%
</style>

这时2张图片可以滚动,下面要添加底部的分页效果:

<script>
export default {
  name: 'CommonGallary',
  data () {
    return {
      swiperOptions: {
        pagination: '.swiper-pagination',
        paginationType: 'fraction'
      }
    }
  }
}
</script>

<style lang="stylus" scoped>
.container >>> .swiper-container
  overflow:inherit

    .swiper-pagination
      color: #fff
      bottom: -1rem
</style>

现在效果就可以实现了:

然后就可以实现循环逻辑部分了:

<template>
<div class="container">
  <div class="wrapper">
    <swiper :options="swiperOptions">
      <swiper-slide v-for="(item, index) in imgs" :key="index">
        <img width="100%" :src="item" />
      </swiper-slide>
      <div class="swiper-pagination"  slot="pagination"></div>
    </swiper>
  </div>
</div>
</template>

<script>
export default {
  name: 'CommonGallary',
  props: {
    imgs: {
      tpye: Array,
      // 默认函数,返回数组
      default () {
        return [
          'http://img1.qunarzz.com/sight/p0/1409/19/adca619faaab0898245dc4ec482b5722.jpg_r_800x800_6edd8174.jpg',
          'http://img1.qunarzz.com/sight/p0/1907/ca/ca68bd95bc36bdba3.img.jpg_r_800x800_33169c4b.jpg']
      }
    }
  },
  data () {
    return {
      swiperOptions: {
        pagination: '.swiper-pagination',
        paginationType: 'fraction'
      }
    }
  }
}
</script>

效果和刚才还是一样的,没问题。

然后把默认 default 函数,返回改为空数组。

default () {
        return []
  }

回到Banner.vue文件,把刚才的2个图片地址先写上:

<common-gallary :imgs="imgs"></common-gallary>

<script>
import CommonGallary from 'common/gallary/Gallary'
export default {
  name: 'DetailBanner',
  components: {
    CommonGallary
  },
  data () {
    return {
      imgs: ['http://img1.qunarzz.com/sight/p0/1409/19/adca619faaab0898245dc4ec482b5722.jpg_r_800x800_6edd8174.jpg', 'http://img1.qunarzz.com/sight/p0/1907/ca/ca68bd95bc36bdba3.img.jpg_r_800x800_33169c4b.jpg']
    }
  }
}
</script>

刷新,效果还是一样的。

下面我们把 common-gallary 组件设置为默认隐藏的,当点击banner的时候才会显示:

<div class="banner" @click="handleBanner">
、、、
</div>
<common-gallary :imgs="imgs" v-show="showGallary"></common-gallary>

<script>
import CommonGallary from 'common/gallary/Gallary'
export default {
  name: 'DetailBanner',
  components: {
    CommonGallary
  },
  data () {
    return {
      showGallary: false,
      imgs: ['http://img1.qunarzz.com/sight/p0/1409/19/adca619faaab0898245dc4ec482b5722.jpg_r_800x800_6edd8174.jpg', 'http://img1.qunarzz.com/sight/p0/1907/ca/ca68bd95bc36bdba3.img.jpg_r_800x800_33169c4b.jpg']
    }
  },
  methods: {
    handleBanner () {
      this.showGallary = true
    }
  }
}
</script>

现在点击banner图片时,可以显示画廊组件了,但是轮播好像滚动有点问题。这个是因为 common-gallary 组件开始是处于隐藏状态,当再次显示时,Swiper计算宽度会有一些问题,导致轮播图无法正常滚动。

打开Gallary.vue文件,添加2个参数:

observeParents:observe应用于Swiper的父元素。当Swiper的父元素变化时,例如window.resize,Swiper更新。

observer:启动动态检查器(OB/观众/观看者),当改变swiper的样式(例如隐藏/显示)或者修改swiper的子元素时,自动初始化swiper。 默认false,不开启,可以使用update()方法更新。

data () {
    return {
      swiperOptions: {
        pagination: '.swiper-pagination',
        paginationType: 'fraction',
        observeParents: true,
        observer: true
      }
    }
  }

OK,回到页面重新刷新,已经可以滚动了。

最后就是点击轮播图,轮播插件给关闭

打开Gallary.vue,给container添加一个点击事件:

<div class="container" @click="handleGallary">

<script>
export default {
  methods: {
    handleGallary () {
      this.$emit('close')
    }
  }
}
</script>

在Banner.vue中接收close:

<common-gallary :imgs="imgs" v-show="showGallary" @close="gallaryClose"></common-gallary>

<script>
import CommonGallary from 'common/gallary/Gallary'
export default {
  methods: {
    gallaryClose () {
      this.showGallary = false
    }
  }
}
</script>

OK,功能完成,可以提交代码了:

git add .
git commit -m "banner及公用画廊组件"
git push

git checkout master
git merge detail-banner
git push
原文地址:https://www.cnblogs.com/joe235/p/12507276.html