1)创建rating文件夹和rating.vue,商家评分用到seller,seller由routerview传入,在rating中接收即可
props: {
seller: {
seller: {
type: Object
}
}
}
2)编写样式, 在评分处引入star组件并编写样式
<div class="overview">
<div class="overview-left">
<h1 class="score">{{seller.score}}</h1>
<div class="title">综合评分</div>
<div class="rank">高于周边商家{{seller.rankRate}}%</div>
</div>
<div class="overview-right">
<div class="score-wrapper">
<span class="title">服务态度</span>
<star :size="36" :score="seller.serviceScore"></star>
<span class="score">{{seller.serviceScore}}</span>
</div>
<div class="score-wrapper">
<span class="title">商品评分</span>
<star :size="36" :score="seller.foodScore"></star>
<span class="score">{{seller.foodScore}}</span>
</div>
<div class="delivery-wrapper">
<span class="title">送达时间</span>
<span class="delivery">{{seller.deliveryTime}}分钟</span>
</div>
</div>
</div>
<split></split>
3)加入media sreen 适应不同的分辨率(overview-left和overview-right处添加),屏幕较小时出现了折行
.ratings
position absolute
top 174px
bottom 0
left 0
width 100%
overflow hidden
.overview
display flex
padding 18px 0 18px 18px
.overview-left
padding-bottom 6px 0
flex 0 0 137px
width 137px
border-right 1px solid rgba(7,17,27,0.1)
text-align center
@media only screen and (max-width 320px)
flex 0 0 110px
width 110px
.score
margin-bottom 6px
line-height 28px
font-size 24px
color rgb(255, 153, 0)
.title
margin-bottom 8px
line-height 12px
font-size 12px
color rgb(7, 17, 27)
.rank
line-height 10px
font-size 10px
color rgb(147, 153, 159)
.overview-right
flex 1
padding 6px 0 6px 24px
@media only screen and (max-width 320px)
padding-left 6px
.score-wrapper
line-height 18px
margin-top 8px
font-size 0
.title
display inline-block
vertical-align top
line-height 18px
font-size 12px
color rgb(7, 17, 27)
.star
display inline-block
vertical-align top
margin 0 12px
.score
display inline-block
vertical-align top
line-height 18px
font-size 12px
color rgb(255, 153, 0)
.delivery-wrapper
font-size 0
.title //span文字之间默认是垂直居中的,可以不用加display vertical-align
display inline-block
vertical-align top
line-height 18px
font-size 12px
color rgb(7, 17, 27)
.delivery
display inline-block
margin-left 12px
vertical-align top
line-height 18px
font-size 12px
color rgb(147, 153, 159)
4)引入并注册split.vue和ratingselect.vue组件中调用
<ratingselect @increment="incrementTotal" :select-type="selectType" :only-content="onlyContent" :ratings="ratings"></ratingselect>
5)food.vue和rating.vue都将评价类型或者是选择类型传递给ratingselect.vue组件,但是传递的数值是不一样的,在这里,:ratings="ratings",指的是随商家的评价,在foods.vue中是:ratings="food.ratings",是对商家店里某一种食物的评价
data () {
return {
ratings: [],
showFlag: false,
selectType: ALL,
onlyContent: true
};
}
6)同goods.vue,在created()函数中拿到rating的API数据
created() {
//请求的ajex地址,成功的回调,拿到一个response
this.$http.get('/api/ratings').then((response) => {
//response是一个属性,将其转化为json对象
response = response.body;
//console.log(response);
if (response.errno === ERR_OK) {
// 数据在data字段中,将goods对象传给header组件,通过:goods
this.ratings = response.data;
// console.log(this.goods);
this.$nextTick(() => {
this.scroll = new BScroll(this.$refs.ratings, {
click: true //允许点击
});
});
}
});
},
7)拿到数据之后编写样式,填充html中的DOM数据
8)绑定BScroll进行滚动
8.1 拿到DOM数据,ref="ratings",将BS初始化写在created函数拿到api数据之后
created() {
//请求的ajex地址,成功的回调,拿到一个response
this.$http.get('/api/ratings').then((response) => {
//response是一个属性,将其转化为json对象
response = response.body;
//console.log(response);
if (response.errno === ERR_OK) {
// 数据在data字段中,将goods对象传给header组件,通过:goods
this.ratings = response.data;
// console.log(this.goods);
this.$nextTick(() => {
this.scroll = new BScroll(this.$refs.ratings, {
click: true //允许点击
});
});
}
});
},
8.2.默认进图商品界面还会导致rating界面来不及渲染,因为nextTicks是异步执行的,所以将默认进入商品界面去除
在main.js中//router.push('/goods'); // 默认进入商家页面
8.3 .点击切换评价列表,和商品详情页类似,引入子组件
<ratingselect @increment="incrementTotal" :select-type="selectType" :only-content="onlyContent" :ratings="ratings"></ratingselect>
子组件已经定义好了data数据和派发函数,在food详情页展示的时候已经写过了
data() {
return {
sType: this.selectType,
oContent: this.onlyContent,
}
},
<div class="ratingselect">
<div class="rating-type" border-1px>
<span class="block positive" @click="select(2,$event)" :class="{'active':sType === 2}">{{desc.all}}<span class="count">{{ratings.length}}</span> </span>
<span class="block positive" @click="select(0,$event)" :class="{'active':sType === 0}">{{desc.positive}}<span class="count">{{positives.length}}</span></span>
<span class="block negative" @click="select(1,$event)" :class="{'active':sType === 1}">{{desc.negative}}<span class="count">{{negatives.length}}</span></span>
</div>
<div @click="toggleContent($event)" class="switch" :class="{'on':oContent}">
<span class="icon-check_circle"></span>
<span class="text">只看有内容的评价</span>
</div>
</div>
select (type, event) { //点击的时候外层是有一个BScroll的,所以要传递event阻止默认点击
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
//将this.selectType设置成传入的参数,而不是food传过来的初始化的值,之后样式就可以随着点击改变了
this.sType = type;
//派发事件通知父组件food.vue selectType的改变,将type值传出去
console.log('ratingselect.vue ' + type);
//this.$emit('se-type', type);
this.$emit('increment', 'selectType', this.sType);
},
toggleContent (event) {
if (!event._constructed) { //浏览器直接return掉,去掉自带click事件的点击
return;
}
this.oContent = !this.oContent;
console.log('ratingselect.vue ' + this.oContent);
// this.$emit('toggle-content', this.oContent);
this.$emit('increment', 'onlyContent', this.oContent);
}
},
在父组件rating.vue中
incrementTotal(type, data) {
this[type] = data;
this.$nextTick(() => {
this.scroll.refresh();
});
},
9. 点击满意不满意和只看内容的评价,评价列表进行刷新,在li列表展示里添加needshow();,needshow中改变的是selectType的值
<div class="rating-wrapper">
<ul>
<li v-for="rating in ratings" :key="rating.id" class="rating-item" v-show="needShow(rating.rateType, rating.text)">
<div class="avatar">
<img :src="rating.avatar" width="28px" height="28px">
</div>
<div class="content">
<h1 class="name">{{rating.username}}</h1>
<div class="star-wrapper">
<star :size="24" :score="rating.score"></star>
<span class="delivery" v-show="rating.deliveryTime">
{{rating.deliveryTime}}
</span>
</div>
<p class="text">{{rating.text}}</p>
<div class="recommend" v-show="rating.recommend && rating.recommend.length"> <!-- 赞或踩和相关推荐 -->
<i class="icon-thumb_up"></i>
<span class="item" v-for="item in rating.recommend" :key="item.id">{{item}}</span>
</div>
<div class="time">
{{rating.rateTime | formatDate}}
</div>
</div>
</li>
</ul>
</div>
needShow(type, text) {
if (this.onlyContent && !text) {
return false;
}
if (this.selectType === ALL) {
return true;
} else {
return type === this.selectType;
}
}
},