vue2.0 饿了么学习笔记(16)rating组件的开发

 

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;
      }
    }
  },






猜你喜欢

转载自blog.csdn.net/qq_22317389/article/details/80459315