一、内容介绍
1、内容
商家详情页主要包括商家的具体信息、公告与活动、商家实景和商家信息。其中商家实景这里实现了纵向滚动,将scrollX设置为true。这一部分利用到了split组件和star组件
2、效果
二、具体实现
1、布局
<template>
<div class="seller" ref="seller">
<div class="seller-content">
<div class="overview">
<h1 class="title">{{seller.name}}</h1>
<div class="desc">
<Star :score="seller.score"></Star>
<span class="text">({{seller.ratingCount}})</span>
<span class="text">月售{{seller.sellCount}}单</span>
</div>
<ul class="remark">
<li class="block">
<h2>起送价</h2>
<div class="content">
<span class="stress">{{seller.minPrice}}</span>元
</div>
</li>
<li class="block">
<h2>商家配送</h2>
<div class="content">
<span class="stress">{{seller.deliveryPrice}}</span>元
</div>
</li>
<li class="block">
<h2>平均配送时间</h2>
<div class="content">
<span class="stress">{{seller.deliveryTime}}</span>分钟
</div>
</li>
</ul>
<div class="favorite" @click="toggleFavorite">
<span class="iconfont icon-shoucang" :class="{active:favorite}"></span>
<span class="text">{{favoriteText}}</span>
</div>
</div>
<Split></Split>
<div class="bulletin">
<h1 class="title">公告与活动</h1>
<div class="content-wrapper">
<p class="content">{{seller.bulletin}}</p>
</div>
<ul v-if="seller.supports" class="supports">
<li class="supports-item" v-for="(item,index) in seller.supports" :key="index">
<span class="icon" :class="classMap[seller.supports[index].type]"></span>
<span class="text">{{seller.supports[index].description}}</span>
</li>
</ul>
</div>
<Split></Split>
<div class="pics">
<h1 class="title">商家实景</h1>
<div class="pic-wrapper" ref="picWrapper">
<ul class="pic-list" ref="picList">
<li class="pic-item" v-for="(pic, index) in seller.pics" :key="index">
<img :src="pic" width="120" height="90" class="pic" alt="">
</li>
</ul>
</div>
</div>
<Split></Split>
<div class="info">
<h1 class="title">商家信息</h1>
<ul>
<li class="info-item" v-for="(info, index) in seller.infos" :key="index">{{info}}</li>
</ul>
</div>
</div>
</div>
</template>
2、滚动实现
_initScroll () {
if (!this.scroll) {
// console.log('3')
this.$nextTick(() => {
this.scroll = new BScroll(this.$refs.seller, {
click: true
})
})
} else {
this.scroll.refresh()
}
if (!this.picSroll) {
let picWidth = 120
let margin = 6
let width = (picWidth + margin) * this.seller.pics.length - margin
this.$refs.picList.style.width = `${width}px`
this.$nextTick(() => {
this.picSroll = new BScroll(this.$refs.picWrapper, {
scrollX: true,
click: true
// eventPassthrough: 'vertical'
})
})
} else {
this.picSroll.refresh()
}
},
三、源码
seller.vue
<template>
<div class="seller" ref="seller">
<div class="seller-content">
<div class="overview">
<h1 class="title">{{seller.name}}</h1>
<div class="desc">
<Star :score="seller.score"></Star>
<span class="text">({{seller.ratingCount}})</span>
<span class="text">月售{{seller.sellCount}}单</span>
</div>
<ul class="remark">
<li class="block">
<h2>起送价</h2>
<div class="content">
<span class="stress">{{seller.minPrice}}</span>元
</div>
</li>
<li class="block">
<h2>商家配送</h2>
<div class="content">
<span class="stress">{{seller.deliveryPrice}}</span>元
</div>
</li>
<li class="block">
<h2>平均配送时间</h2>
<div class="content">
<span class="stress">{{seller.deliveryTime}}</span>分钟
</div>
</li>
</ul>
<div class="favorite" @click="toggleFavorite">
<span class="iconfont icon-shoucang" :class="{active:favorite}"></span>
<span class="text">{{favoriteText}}</span>
</div>
</div>
<Split></Split>
<div class="bulletin">
<h1 class="title">公告与活动</h1>
<div class="content-wrapper">
<p class="content">{{seller.bulletin}}</p>
</div>
<ul v-if="seller.supports" class="supports">
<li class="supports-item" v-for="(item,index) in seller.supports" :key="index">
<span class="icon" :class="classMap[seller.supports[index].type]"></span>
<span class="text">{{seller.supports[index].description}}</span>
</li>
</ul>
</div>
<Split></Split>
<div class="pics">
<h1 class="title">商家实景</h1>
<div class="pic-wrapper" ref="picWrapper">
<ul class="pic-list" ref="picList">
<li class="pic-item" v-for="(pic, index) in seller.pics" :key="index">
<img :src="pic" width="120" height="90" class="pic" alt="">
</li>
</ul>
</div>
</div>
<Split></Split>
<div class="info">
<h1 class="title">商家信息</h1>
<ul>
<li class="info-item" v-for="(info, index) in seller.infos" :key="index">{{info}}</li>
</ul>
</div>
</div>
</div>
</template>
<script>
import BScroll from 'better-scroll'
import Star from '@/components/Star/star'
import Split from '@/components/split/split'
export default {
props: {
seller: {
type: Object
}
},
data () {
return {
sellers: this.seller,
favorite: false
}
},
components: {
Star,
Split
},
computed: {
favoriteText () {
return this.favorite ? '已收藏' : '收藏'
}
},
created () {
// 定义一个数组用来存储折扣的图标
this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee']
},
// watch: {
// 'sellers' () {
// console.log('1')
// this._initScroll()
// }
// },
mounted () {
// console.log('2')
this._initScroll()
},
methods: {
_initScroll () {
if (!this.scroll) {
// console.log('3')
this.$nextTick(() => {
this.scroll = new BScroll(this.$refs.seller, {
click: true
})
})
} else {
this.scroll.refresh()
}
if (!this.picSroll) {
let picWidth = 120
let margin = 6
let width = (picWidth + margin) * this.seller.pics.length - margin
this.$refs.picList.style.width = `${width}px`
this.$nextTick(() => {
this.picSroll = new BScroll(this.$refs.picWrapper, {
scrollX: true,
click: true
// eventPassthrough: 'vertical'
})
})
} else {
this.picSroll.refresh()
}
},
toggleFavorite (event) {
if (!event._constructed) {
return
}
this.favorite = !this.favorite
}
}
}
</script>
<style>
.seller{
position: absolute;
top: 174px;
bottom: 0;
/* left: 0; */
width: 100%;
overflow: hidden;
}
.seller .overview{
padding: 18px;
position: relative;
}
.seller .overview .title{
margin-bottom: 8px;
font-size: 14px;
line-height: 14px;
color: rgb(7,17,27);
}
.seller .overview .desc{
font-size: 0;
border-bottom: 1px solid rgba(7,17,27,0.1);
padding-bottom: 18px;
}
.seller .overview .desc .star{
display: inline-block;
margin-right: 8px;
vertical-align: top;
}
.seller .overview .desc .text{
display: inline-block;
margin-right: 12px;
line-height: 18px;
vertical-align: top;
font-size: 10px;
color: rbg(77,85,93);
}
.seller .overview .remark{
display: flex;
padding-top: 18px;
}
.seller .overview .remark .block{
flex: 1; /**都设置为1就会等分 */
text-align: center;
border-right: 1px solid rgba(7,17,27,0.1);
}
.seller .overview .remark li:last-child{
border-right: none;
}
.seller .overview .remark .block h2{
margin-bottom: 4px;
font-size: 10px;
color: rgb(147,153,159);
line-height: 10px;
}
.seller .overview .remark .block .content{
line-height: 24px;
font-size: 10;
color: rgb(7,17,27);
}
.seller .overview .remark .block .content .stress{
font-size: 24px;
}
.seller .overview .favorite{
position: absolute;
width: 50px;
right:18px;
top: 18px;
text-align: center;
}
.seller .overview .favorite .iconfont{
display: block;
margin-bottom: 4px;
color: #d6d4d9;
line-height: 24px;
font-size: 24px;
}
.seller .overview .favorite .active{
color: rgb(240,20,20);
}
.seller .overview .favorite .text{
line-height: 10px;
font-size: 10px;
color: rgb(77,85,93);
}
.seller .bulletin{
padding: 18px 18px 0 18px;
}
.seller .bulletin .title{
margin-bottom: 8px;
font-size: 14px;
line-height: 14px;
color: rgb(7,17,27);
}
.seller .bulletin .content-wrapper{
padding: 0 12px 16px 12px;
border-bottom: 1px solid rgba(7,17,27,0.1);
}
.seller .bulletin .content-wrapper .content{
line-height: 24px;
font-size: 12px;
color: rgb(240,20,20);
}
.seller .bulletin .supports .supports-item{
padding: 16px 12px;
font-size: 1px;
border-bottom: 1px solid rgba(7,17,27,0.1);
}
.seller .bulletin .supports .supports-item .icon{
display: inline-block;
width: 16px;
height: 16px;
vertical-align: top;
margin-right: 6px;
background-size: 16px 16px;
background-repeat: no-repeat;
}
.seller .bulletin .supports .supports-item .decrease{
background-image: url('./css/decrease_2@2x.png')
}
.seller .bulletin .supports .supports-item .discount{
background-image: url('./css/discount_2@2x.png')
}
.seller .bulletin .supports .supports-item .guarantee{
background-image: url('./css/guarantee_2@2x.png')
}
.seller .bulletin .supports .supports-item .invoice{
background-image: url('./css/invoice_2@2x.png')
}
.seller .bulletin .supports .supports-item .special{
background-image: url('./css/special_2@2x.png')
}
.seller .bulletin .supports .supports-item .text{
line-height: 16px;
font-size: 12px;
color: rgb(7,17,27);
}
.seller .bulletin .supports li:last-child{
border-bottom: none;
}
.seller .seller-content .pics{
padding: 18px;
}
.seller .pics .title{
margin-bottom: 12px;
font-size: 14px;
line-height: 14px;
color: rgb(7,17,27);
}
.seller .pics .pic-wrapper{
width: 100%;
overflow: hidden;
white-space: nowrap;
}
.seller .pics .pic-wrapper .pic-item{
display: inline-block;
margin-right: 6px;
}
.seller .pics .pic-wrapper .pic-list li:last-child{
margin: 0;
}
.seller .info {
padding: 18px 18px 0 18px;
}
.seller .info .title{
padding-bottom: 12px;
font-size: 14px;
line-height: 14px;
color: rgb(7,17,27);
border-bottom: 1px solid rgba(7,17,27,0.1);
}
.seller .info .info-item{
padding: 16px 12px;
line-height: 16px;
border-bottom: 1px solid rgba(7,17,27,0.1);
color: rgb(7,17,27);
font-size: 12px;
}
.seller .info li:last-child{
border: none;
}
</style>