在上篇文章咱們將項目頭部模塊進行了編寫與數據渲染。css
本篇文章咱們進一步深刻項目設計評價組件。html
分析頁面vue
如圖所示,點菜,評價,商家,爲導航,咱們點擊評價的時候,直接跳轉評價頁面。react
評價頁面由商家評分一欄,評論列表構成,評論列表支持:所有,有圖,點評三種篩選。webpack
綜上咱們如今開始設計評論組件:ios
創建組件文件夾web
1.css圖片的存放axios
針對組件引用的圖片可能產生變更性,咱們將組件內的圖片放入組件文件夾內,進行引用。使得組件更加便於維護。api
2.路徑配置app
build/webpack.base.conf.js內:
alias: { 'vue$': 'vue/dist/vue.esm.js',//自動補全設置 '@': resolve('src'), 'components': resolve('./src/components') }
經過alias重命名設置對組件導入模塊時進行了重命名。
實際在導入須要的組件寫法:
// 舉個例子,導入Ratings組價能夠寫成 import Ratings from 'components/Ratings/Ratings'
圖片存放,路徑配置完成之後咱們創建Ratings文件夾並進入:
根據分析頁面結構整理之後因此咱們先把頁面結構搭建出來:
在Ratings.vue中:
//設置容器存放評論組件 <template> <div class="ratings" ref='ratingView'> <div class="ratings-wrapper"> //細化咱們組件 </div> </div> </template>
如今咱們設計商家評分,口味,包裝,等結構以下圖:
<div class="overview"> <div class="overview-left"> <div class="comment-score"> <p class="score">{{ratings.comment_score}}</p> <p class="text">商家評分</p> </div> <div class="other-score"> <div class="quality-score item"> <span class="text">口味</span> <Star :score='ratings.quality_score' class='star'></Star> <span class="score">{{ratings.quality_score}}</span> </div> <div class="pack-score item"> <span class="text">包裝</span> <Star :score='ratings.pack_score' class='star'></Star> <span class="score">{{ratings.pack_score}}</span> </div> </div> </div> <div class="overview-right"> <div class="delivery-score"> <p class="score">{{ratings.delivery_score}}</p> <p class="text">配送評分</p> </div> </div> </div>
實現評論中選項卡(所有,有圖,點評),列表頁面:
<div class="content"> <div class="rating-select" v-if="ratings.tab"> <span class="item" @click="selectTypeFn(2)" :class="{'active':selectType==2}"> {{ratings.tab[0].comment_score_title}} </span> <span class="item" @click="selectTypeFn(1)" :class="{'active':selectType==1}"> {{ratings.tab[1].comment_score_title}} </span> <span class="item" @click="selectTypeFn(0)" :class="{'active':selectType==0}"> <img src="./icon_sub_tab_dp_normal@2x.png" v-show="selectType!=0" /> <img src="./icon_sub_tab_dp_highlighted@2x.png" v-show="selectType==0" /> {{ratings.tab[2].comment_score_title}} </span> </div> <div class="labels-view"> <span v-for="item in ratings.labels" class="item" :class="{'highligh':item.label_star>0}"> {{item.content}}{{item.label_count}} </span> </div> //評論列表 <ul class="rating-list"> <li v-for="comment in selectComments" class="comment-item"> <div class="comment-header"> <img :src="comment.user_pic_url" v-if="comment.user_pic_url" /> <img src="./anonymity.png" v-if="!comment.user_pic_url" /> </div> <div class="comment-main"> <div class="user"> {{comment.user_name}} </div> <div class="time"> {{fotmatDate(comment.comment_time)}} </div> <div class="star-wrapper"> <span class="text">評分</span> <Star :score='comment.order_comment_score' class='star'></Star> </div> <div class="c_content" v-html="commentStr(comment.comment)"></div> <div class="img-wrapper" v-if="comment.comment_pics.length"> <img v-for="item in comment.comment_pics" :src="item.thumbnail_url" /> </div> </div> </li> </ul> </div>
結構搭建完成,下面咱們爲組件傳入對應的數據。
父子組件通訊
Ratings.vue
導入依賴的子組件:
<script> // 導入Star組件 import Star from 'components/Star/Star' // 導入Split組件 import Split from 'components/Split/Split' // 導入BScroll組件 import BScroll from 'better-scroll'; </script> //設置選項卡變量 const ALL = 2; // 所有 const PICTURE = 1; // 帶圖片 const COMMENT = 0; // 點評
下面咱們開始初始化data,在created鉤子內發起請求。
ratings數據部分展現:
export default { data() { return { ratings: {},//存放請求到的數據 selectType: ALL,//默認展現所有 } }, created() { // 經過axios發起get請求 let that = this; this.$axios.get('/api/ratings') .then(function(response) { // 獲取到數據 var dataSource = response.data; if(dataSource.code == 0) { that.ratings = dataSource.data;//將請求到的數據引用到data()中 // 初始化滾動 that.$nextTick(() => { if(!that.scroll) { that.scroll = new BScroll(that.$refs.ratingView, { click: true }); } else { that.scroll.refresh(); } }); } }) .catch(function(error) { // 出錯處理 console.log(error); }); } } </script>
注意$refs與設置容器中的ref='ratingView'咱們用BScroll來操做dom,因此使用了vue的ref API
https://cn.vuejs.org/v2/api/#ref
methods: { selectTypeFn(type) { this.selectType = type; // 刷新操做 this.$nextTick(() => { this.scroll.refresh(); }); }, fotmatDate(time) { let date = new Date(time * 1000); // 時間格式 let fmt = 'yyyy.MM.dd'; if(/(y+)/.test(fmt)) { // 年 let year = date.getFullYear().toString(); fmt = fmt.replace(RegExp.$1, year); } if(/(M+)/.test(fmt)) { // 月 let mouth = date.getMonth() + 1; if(mouth < 10) { mouth = '0' + mouth; } fmt = fmt.replace(RegExp.$1, mouth); } if(/(d+)/.test(fmt)) { // 日 let mydate = date.getDate(); if(mydate < 10) { mydate = '0' + mydate; } fmt = fmt.replace(RegExp.$1, mydate); } return fmt; }, commentStr(content) { let rel = /#[^#]+#/g; return content.replace(rel, '<i>$&</i>'); } }
在methods中咱們定義:
注意selectTypeFn函數內在咱們點擊對應的選項卡後使用 $nextTick()條用scroll刷新列表;
$nextTick()https://cn.vuejs.org/v2/guide...
經過計算屬性將數據傳入class爲rating-list模板中:
須要再次注意方法與計算屬性調用方法等區別,以前咱們對比過,須要詳細瞭解,還請閱讀以前文章,或官方文檔。
computed: { selectComments() { if(this.selectType == ALL) { // 所有 return this.ratings.comments; } else if(this.selectType == PICTURE) { // 有圖 let arr = []; this.ratings.comments.forEach((comment) => { if(comment.comment_pics.length) { arr.push(comment); } }); return arr; } else { // 點評 return this.ratings.comments_dp.comments; } } },
使用引入的組件:
components: { Star, Split, BScroll }
Split組件就是上圖標記的分隔線。
星級評分的邏輯實現
新建Star文件
星星展現形式爲 全星,半星,無星 經過for循環搭建好star結構:
<template> <div class="star"> <!-- itemClass: on、half、off --> <span v-for="itemClass in itemClasses" :class="itemClass" class="star-item"> </span> </div> </template>
經過props接受父組件傳來的score值,並在star內使用,
經過計算屬性對star內的score進行處理,
<script> // 星星長度 const LENGTH = 5; // 星星對應class const CLS_ON = 'on'; const CLS_HALF = 'half'; const CLS_OFF = 'off'; export default{ props: {//經過父組件傳入score,而且在star組件內做爲「data()」使用 score: { type: Number//指定類型 數字 } }, computed: { itemClasses() { let result = []; // 4.7 => 4.5 3.9 => 3.5 4.1 => 4.0 // 對分數進行處理,向下取0.5的倍數 let score = Math.floor(this.score*2) / 2; // 小數,控制半星 let hasDecimal = score % 1 !== 0; // 整數,控制全星 let integer = Math.floor(score); // 全星 for (let i=0; i<integer; i++) { result.push(CLS_ON); } // 半星 if(hasDecimal){ result.push(CLS_HALF); } // 補齊 while(result.length < LENGTH){ result.push(CLS_OFF); } return result; } } } </script>
到此咱們從評價組件的頁面分析,拆出了合理的模板結構,接着配置圖片,組件引用的路徑,節省了咱們在開發中的時間,最後也是最重要的是數據的渲染,以及星級評分的實現。過程當中,咱們再次加深對vue的props,methods,computed,$nextTick()等理解。
以上就是本篇所有內容,下篇咱們將會細化商品展現頁面,咱們下篇見。