景点详情模块
搜索页面初步实现和跳转
在views文件夹下新建 Search.vue
<template>
<!-- 搜索页面 -->
<div class="page-search">
<!-- 标题 -->
<van-nav-bar title="搜索景点" />
<!-- 搜索框 -->
<van-search
v-model="value"
show-action
label="景点"
placeholder="请输入搜索关键词"
@search="onSearch"
>
<template #action>
<div @click="onSearch">搜索</div>
</template>
</van-search>
<!-- 列表 -->
<div class="sight-list">
<SightItem v-for="item in dataList"
:key="item.id"
:item="item"/>
</div>
<!-- 分页 -->
<van-pagination v-model="currentPage" :total-items="totalItems" :items-per-page="perPage" />
<!-- 页脚 -->
<TripFooter/>
</div>
</template>
<script>
import SightItem from '@/components/common/ListSight'
import TripFooter from '@/components/common/Footer'
export default {
data () {
return {
// 景点名称
sightName: '',
// 景点列表的数据
dataList: [],
// 总记录数
totalItems: 0,
// 当前的页码
currentPage: 1,
// 每页数据的大小
perPage: 5
}
},
components: {
SightItem,
TripFooter
},
methods: {
onSearch () {
console.log('onSearch')
}
}
}
</script>
复制代码
设置路由
router下的index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Search from '../views/Search.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/search',
name: 'Search',
component: Search
}
]
const router = new VueRouter({
routes
})
export default router
复制代码
设置路由的跳转 Footer.vue
<template>
<!-- 底部导航 -->
<div>
<van-tabbar v-model="active" route>
<van-tabbar-item name="home" icon="wap-home-o" :to="{name: 'Home'}">首页</van-tabbar-item>
<van-tabbar-item name="search" icon="search" :to="{name: 'Search'}">搜索</van-tabbar-item>
<van-tabbar-item name="mine" icon="user-o">我的</van-tabbar-item>
</van-tabbar>
</div>
</template>
<script>
export default {
data () {
return {
active: 'home'
}
}
}
</script>
复制代码
去掉App.vue中多余的内容
<template>
<div id="app">
<router-view/>
</div>
</template>
<style lang="less">
@import "./assets/style/common.less";
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
复制代码
效果:
点击搜索按钮跳转到搜索页面
景点详情页
views文件夹下新建sight文件夹
新建五个vue文件
景点列表 SightList.vue
景点详情 SightDeatail.vue
景点介绍 SightInfo.vue
评论列表 SightComment.vue
景点下的图片 SightImage.vue
内容暂时均为
<template>
<div class="page-sight-info"></div>
</template>
复制代码
添加路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Search from '../views/Search.vue'
import SightList from '../views/sight/SightList.vue'
import SightDeatail from '../views/sight/SightDeatail.vue'
import SightInfo from '../views/sight/SightInfo.vue'
import SightComment from '../views/sight/SightComment.vue'
import SightImage from '../views/sight/SightImage.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/search',
name: 'Search',
component: Search
},
// 景点列表
{
path: '/search/list',
name: 'SightList',
component: SightList
},
// 景点详情
{
path: '/sight/detail/:id',
name: 'SightDeatail',
component: SightDeatail
},
// 景点介绍
{
path: '/sight/info/:id',
name: 'SightInfo',
component: SightInfo
},
// 评论列表
{
path: '/sight/comment/:id',
name: 'SightComment',
component: SightComment
},
// 景点下的图片
{
path: '/sight/image/:id',
name: 'SightImage',
component: SightImage
}
]
const router = new VueRouter({
routes
})
export default router
复制代码
修改组件的跳转
common文件夹下的ListSight.vue 的a标签
<template>
<router-link class="sight-item"
:to="{ name: 'SightDeatail', params: { id: item.id }}">
<img :src="item.main_img" alt="">
<div class="right">
<h5>{{ item.name }}</h5>
<van-rate v-model="item.score" readonly/>
<div class="tips">{{ item.comment_count }}人点评 | 100%满意</div>
<div class="tips light">{{ item.province }} - {{ item.city }}</div>
<div class="line-price">¥ {{ item.min_price }} 起</div>
</div>
</router-link>
</template>
<script>
export default {
props: ['item']
}
</script>
<style lang="less">
.sight-item {
display: flex;
margin-top: 10px;
border-bottom: 1px solid #f6f6f6;
img {
width: 100px;
height: 100px;
}
h5 {
color: #212121;
font-size: 14px;
padding: 5px 0;
margin: 0;
}
.right {
text-align: left;
flex-grow: 1;
text-align: left;
justify-content: left;
padding-left: 5px;
position: relative;
}
.line-price {
position: absolute;
right: 10px;
top: 20px;
display: inline-block;
color: #f50;
font-size: 16px;
font-weight: bold;
}
.tips {
font-size: 12px;
color: #666;
&.light {
color: #999;
}
}
}
</style>
复制代码
Hot.vue
<template>
<div class="home-hot-box">
<!-- 导航 -->
<van-cell
icon="/static/home/hot/fire.png"
title="热门推荐"
title-style="text-align:left"
value="全部榜单"
is-link
:to="{name: 'SightList', query: {name:'热门推荐'}}" />
<!-- 列表 -->
<div class="box-main">
<router-link class="hot-item"
v-for="item in dataList"
:key="item.id"
:to="{ name: 'SightDeatail', params: { id: item.id }}">
<div class="img">
<span></span>
<img :src="item.main_img" alt="">
</div>
<h5 class="van-ellipsis">{{ item.name }}</h5>
<div class="line-price">
<span class="price">¥{{ item.min_price }}</span>起
</div>
</router-link>
</div>
</div>
</template>
<script>
import { ajax } from '@/utils/ajax'
import { SightApis } from '@/utils/apis'
export default {
data () {
return {
dataList: []
}
},
methods: {
getDataList () {
ajax.get(SightApis.sightListUrl, {
params: {
is_hot: 1
}
}).then(({ data }) => {
this.dataList = data.objects
})
}
},
created () {
// 查询接口数据
this.getDataList()
}
}
</script>
<style lang="less">
.home-hot-box {
padding: 0 10px;
.van-cell {
padding: 10px 0;
}
.box-main {
width: 100%;
display: flex;
padding-top: 10px;
overflow-x: scroll;
}
.hot-item {
display: flex;
flex-direction: column;
width: 100px;
margin-right: 10px;
padding-bottom: 10px;
.img {
position: relative;
span {
position: absolute;
left: 0;
top: 0;
display: inline-block;
width: 42px;
height: 20px;
z-index: 10;
}
img {
width: 100px;
height: 100px;
}
}
h5 {
color: #212121;
padding: 2px 0;
font-size: 12px;
margin: 0;
}
.line-price {
color: #212121;
font-size: 12px;
.price {
color: #f50;
font-size: 13px;
}
}
&:nth-child(1) .img span {
background: url(/static/home/hot/top1.png) no-repeat;
background-size: 100% auto;
}
&:nth-child(2) .img span {
background: url(/static/home/hot/top2.png) no-repeat;
background-size: 100% auto;
}
&:nth-child(3) .img span {
background: url(/static/home/hot/top3.png) no-repeat;
background-size: 100% auto;
}
}
}
</style>
复制代码
Fine.vue
<template>
<!-- 精选景点 -->
<div class="home-fine-box">
<!-- 导航 -->
<van-cell
icon="location-o"
title="精选景点"
title-style="text-align:left"
value="全部榜单"
is-link
:to="{name: 'SightList', query: {name:'精选景点'}}"/>
<!-- 列表 -->
<div class="box-main">
<SightItem v-for="item in dataList"
:key="item.id"
:item="item"/>
</div>
</div>
</template>
<script>
import { ajax } from '@/utils/ajax'
import { SightApis } from '@/utils/apis'
import SightItem from '@/components/common/ListSight'
export default {
components: {
SightItem
},
data () {
return {
dataList: []
}
},
methods: {
getDataList () {
ajax.get(SightApis.sightListUrl, {
params: {
is_top: 1
}
}).then(({ data }) => {
this.dataList = data.objects
})
}
},
created () {
this.getDataList()
}
}
</script>
<style lang="less">
.home-fine-box {
padding: 0 10px;
.van-cell {
padding: 10px 0;
}
.box-main {
padding-bottom: 50px;
}
}
</style>
复制代码
跳转效果
点击热门推荐或精选景点
编写评论列表组件
components文件夹下
新建sight文件夹
新建 CommentItem.vue
<template>
<!-- 评论列表的每一项 -->
<div class="comment-item-box">
<div class="cmt-header">
<div class="rate">
<van-rate v-model="value"
allow-half
readonly
void-icon="star"
void-color="#eee"/>
</div>
<div class="user">张三*** 2020-02-02</div>
</div>
<div class="cmt-content">
<p>评论内容</p>
</div>
<!-- 图片列表 -->
<div class="cmt-imgs" @click="show=true">
<van-image width="100" height="100" src="https://img.yzcdn.cn/vant/cat.jpeg"/>
</div>
<van-image-preview v-model="show" :images="images" @change="onChange">
<template v-slot:index>第{{ index+1 }}页</template>
</van-image-preview>
</div>
</template>
<script>
export default {
data () {
return {
show: false,
index: 0,
images: [
'https://img.yzcdn.cn/vant/apple-1.jpg',
'https://img.yzcdn.cn/vant/apple-2.jpg'
],
value: 4.5
}
},
methods: {
onChange (index) {
this.index = index
}
}
}
</script>
<style lang="less">
.comment-item-box {
padding: 5px 10px;
border-bottom: 1px solid #f6f6f6;
.cmt-header {
display: flex;
justify-content: space-between;
.user {
font-size: 12px;
}
}
.cmt-content {
color: #616161;
padding: 5px 0;
text-align: left;
font-size: 12px;
line-height: 2.0;
}
.cmt-imgs {
padding: 5px;
text-align: left;
margin-right: 5px;
}
}
</style>
复制代码
编写景点详情页内容
SightDeatail.vue
<template>
<!-- 景点详情 -->
<div class="pafe-sight-detail">
<!-- 页面头部 -->
<van-nav-bar
left-text="返回"
left-arrow
fixed
@click-left="goBack"
/>
<!-- 大图 -->
<div class="sight-banner">
<van-image src="/static/home/hot/h1_max.jpg" width="100%" height="100%"/>
<div class="tips">
<router-link class="pic-sts" :to="{name: 'SightImage', params: {id: 123}}">
<van-icon name="video-o" />
<span>10 图片</span>
</router-link>
<div class="title">景点标题</div>
</div>
</div>
<!-- 评分、景点介绍 -->
<div class="sight-info">
<div class="left">
<div class="info-title">
<strong>5分</strong>
<small>很棒</small>
</div>
<div class="info-tips">50 评论</div>
<van-icon name="arrow" />
</div>
<div class="right">
<div class="info-title">
<span>景点介绍</span>
</div>
<div class="info-tips">开放时间、贴士</div>
<van-icon name="arrow" />
</div>
</div>
<!-- 地址信息 -->
<van-cell title="广东省广东市番禺区番禺大道" icon="location-o"
is-link
:title-style="{'text-align': 'left'}">
<template #right-icon>
<van-icon name="arrow" />
</template>
</van-cell>
<!-- 门票列表 -->
<div class="sight-ticket">
<van-cell title="门票" icon="bookmark-o" title-style="text-align:left"/>
<div class="ticket-item" v-for="i in 5" :key="i">
<div class="left">
<div class="title">成人票</div>
<div class="tips">
<van-icon name="clock-o" />
<span>7点之前可以预定</span>
</div>
<div class="tags">
<van-tag mark type="primary">标签1</van-tag>
</div>
</div>
<div class="right">
<div class="price">
<span>¥</span>
<strong>65</strong>
</div>
<router-link to="#">
<van-button type="warning" size="small">预定</van-button>
</router-link>
</div>
</div>
</div>
<!-- 用户评价 -->
<div class="sight-comment">
<van-cell title="热门评论" icon="comment-o" title-style="text-align:left"/>
<CommentItem/>
<router-link class="link-more" :to="{name: 'SightComment', params: {id}}">查看更多</router-link>
</div>
</div>
</template>
<script>
// 评论项组件
import CommentItem from '@/components/sight/CommentItem'
export default {
data () {
return {
id: ''
}
},
components: {
CommentItem
},
methods: {
goBack () {
this.$router.go(-1)
}
},
created () {
this.id = this.$$route.params.id
}
}
</script>
<style lang="less">
.pafe-sight-detail {
.van-nav-bar {
background-color: transparent;
}
// 景点大图
.sight-banner{
position: relative;
.tips {
position: absolute;
left: 10px;
bottom: 10px;
font-size: 16px;
color: #fff;
.pic-sts {
color: #fff;
border-radius: 30px;
font-size: 14px;
background-color: rgba(0,0,0,0.4);
}
}
}
// 评分、景点介绍
.sight-info {
display: flex;
background-color: #fff;
border-bottom: 1px solid #f6f6f6;
& > div {
flex: 1;
position: relative;
}
.right {
border-left: 1px solid #f6f6f6;
}
.info-title {
text-align: left;
padding: 5px 10px;
strong {
color: #ff8300;
}
}
.info-tips {
color: #999;
font-size: 12px;
text-align: left;
padding: 5px 10px;
}
.van-icon {
position: absolute;
right: 5px;
top: 5px;
}
}
// 门票列表
.sight-ticket {
margin-top: 10px;
background-color: #fff;
.ticket-item {
display: flex;
border-bottom: 1px solid #f6f6f6;
padding-bottom: 10px;
.left {
flex: 1;
text-align: left;
padding: 5px 10px;
.title {
padding: 5px 0;
}
.tips {
font-size: 12px;
}
}
.right {
width: 100px;
.price {
color: #ff9800;
strong {
font-size: 20px;
}
}
}
}
}
// 评论列表
.sight-comment {
margin-top: 10px;
background-color: #fff;
}
// 查看更多
.link-more {
display: block;
color: #666;
padding: 10px;
}
}
</style>
复制代码
效果:
近期评论