• 外卖webAPP(四)


    一,评价shopRtings页面搭建

    在vuex中获取数据,商家评价列表数据

      mounted(){
        this.$store.dispatch('getShopRatings')
      },
      computed:{
        ...mapState(['info', 'ratings'])
      }

    填充数据, 根据rateType的标识来来判断是向上的拇指还是向下的拇指

     <div class="recommend">
                    <span class="iconfont" :class="rating.rateType===0 ? 'icon-thumb_up' : 'icon-thumb_down'"></span>
                    <span class="item" v-for="(item, index) in rating.recommend" :key="index">{{item}}</span>
                  </div>

    评论信息可以点击滚动,需要在获取数据后(vuex中通知评价组件),创建better-scroll实例

      mounted () {
          this.$store.dispatch('getShopRatings', () => {
            this.$nextTick(() => {
              new BScroll(this.$refs.ratings, {
                click: true
              })
            })
          })
        },
     // 异步获取商家评价列表
      async getShopRatings({commit}, callback) {
        const result = await reqShopRatings()
        if (result.code === 0) {
          const ratings = result.data
          commit(RECEIVE_RATINGS, {ratings})
          // 数据更新了, 通知一下组件
          callback && callback()
        }
      },

    关于内容的过滤,全部,满意,不满意,或者是否有内容,这两种条件来过滤评论内容

     全部的数量,满意的数量,不满意的数量

     在ratings数组中每个对象都有个rateType属性,0为满意,1为不满意,在vuex中的getters中计算满意的个数

      positiveSize (state) {
        return state.ratings.reduce((preTotal, rating) => preTotal + (rating.rateType===0?1:0) , 0)
      }

    填充模板

    ...mapGetters(['positiveSize']),
      <div class="ratingselect">
            <div class="rating-type border-1px">
              <span class="block positive" :class="{active: selectType===2}" @click="setSelectType(2)">
                全部<span class="count">{{ratings.length}}</span>
              </span>
              <span class="block positive" :class="{active: selectType===0}" @click="setSelectType(0)">
                满意<span class="count">{{positiveSize}}</span>
              </span>
              <span class="block negative" :class="{active: selectType===1}" @click="setSelectType(1)">
                不满意<span class="count">{{ratings.length-positiveSize}}</span>
              </span>
            </div>
            <div class="switch" :class="{on: onlyShowText}" @click="toggleOnlyShowText">
              <span class="iconfont icon-check_circle"></span>
              <span class="text">只看有内容的评价</span>
            </div>
          </div>

    类名on,代表只有内容的评价是否勾选,定义一个变量onlyShowText默然勾选,点击勾选后,标识状态取反

        data () {
          return {
            onlyShowText: true, // 是否只显示有文本的
            selectType: 2 , // 选择的评价类型: 0满意, 1不满意, 2全部
          }
        },
     toggleOnlyShowText () {
            this.onlyShowText = !this.onlyShowText
          }

    点击满意,不满意,全部按钮,定义一个变量selectType来标识他们的意思, 选择的评价类型: 0满意, 1不满意, 2全部, 默认全部

    active类名动态切换颜色
    setSelectType (selectType) {
            this.selectType = selectType
          },

    过滤数组,通过两个条件,来过滤筛选之后的数组

     filterRatings () {
            // 得到相关的数据
            const {ratings, onlyShowText, selectType} = this
    
            // 产生一个过滤新数组
            return ratings.filter(rating => {
              const {rateType, text} = rating
              /*
                条件1:
                    selectType: 0/1/2
                    rateType: 0/1
                    selectType===2 || selectType===rateType
                条件2
                    onlyShowText: true/false
                    text: 有值/没值
                    !onlyShowText || text.length>0
               */
              return (selectType===2 || selectType===rateType) && (!onlyShowText || text.length>0)
            })
          }

    填充模板

    <div class="rating-wrapper">
            <ul>
              <li class="rating-item" v-for="(rating, index) in filterRatings" :key="index">
                <div class="avatar">
                  <img width="28" height="28" :src="rating.avatar">
                </div>
                <div class="content">
                  <h1 class="name">{{rating.username}}</h1>

     二,商家shopInfo组件页面搭建

    2.1.,从vuex中获取数据info

      mounted(){
        this.$store.dispatch('getShopInfo')
      },
    
      computed:{
        ...mapState(['info'])
      }

    填充数据

     获取服务的标签按钮有三个不同颜色,而获取的数据info.supports数组中,遍历的对象都有type属性,0代表绿色, 1红色,2黄色

    我们需要将标签颜色动态渲染,将三个颜色类名定义一个数组,利用type属性来一一对应

     data () {
          return {
            supportClasses: ['activity-green', 'activity-red', 'activity-orange']
          }
        },
       <section class="section">
            <h3 class="section-title">活动与服务</h3>
            <div class="activity">
              <div class="activity-item" v-for="(support, index) in info.supports" :key="index"
                  :class="supportClasses[support.type]">
                <span class="content-tag">
                  <span class="mini-tag">{{support.name}}</span>
                </span>
                <span class="activity-content">{{support.content}}</span>
              </div>
            </div>
          </section>
    2.2,创建商家页面时,要创建better-scroll实例,可以实现滚动
    商家实景图片,也要创建better-scroll实例,可以实现滚动
    首先数据info,要回来,第二是数据回来最后一次刷新页面,调用this.$nextTick()

    方法有两种

    第一种,在mouted阶段,dispatch获取到info数据,传一个回调函数,然后vuex中actions发送请求,获取到info数据,在调用这个回调,通知商家页面去做创建scroll的逻辑

     mounted(){
      // 数据回来了,创建bette-scroll
        this.$store.dispatch('getShopInfo',()=>{
            
          this.$nextTick(()=>{
              // info页面滚动
            new BScroll('.shop-info',{
              click : true
            })
    
             // 获取uldom对象
            const ulNode = this.$refs.picsUl
            const liWidth = 120
            const space = 6
            // 图片数量
            const counts = this.info.pics.length
            // 整个图片盒子长度
            ulNode.style.width =  (liWidth + space) *counts -space  +'px'
            console.log(ulNode.style.width)
             // 商家实景图片滚动,水平滚动
            new BScroll('.pic-wrapper',{
              // click: true,
              scrollX :true
            })
    
          })
          <section class="section">
            <h3 class="section-title">商家实景</h3>
            <div class="pic-wrapper">
              <ul class="pic-list" ref="picsUl">
                <li class="pic-item" v-for="(pic, index) in info.pics" :key="index">
                  <img width="120" height="90" :src="pic"/>
                </li>
              </ul>
            </div>
          </section>
      // 异步获取商家信息
      async getShopInfo({ commit },callback) {
        const result = await reqShopInfo()
        if (result.code === 0) {
          const info = result.data
          commit('RECEIVE_INFO', info)
          callback && callback()
        }
      },

    此时实景图片不会滚动,原因是ul父元素的宽度347, 而而li中的图片宽度120,右边距6, 父元素ul不是自适应li的宽度,

    解决,我们需要根据li计算ul的宽度, ulNode.style.width =  (liWidth + space) *counts -space  +'px'

    方法二,不需要向vuex中的actons传递回调函数
    第一次mouted时,获取图片个数报错,需要判断this.info.pics是否有值
     
    将创建scroll的逻辑封装成一个函数,在mouted阶段调用, 再次刷新页面,监视数据时在此调用
     

    注:1.切换回路由组件,组件生命周期消失了又创建了,会重新执行mounted钩子函数(数据和页面已经都回来了),不会执行watch

    2.如果页面刷新了,不会重新执行mounted,需要监听数据变化,执行wacth监听,此时还要先执行this.nextTick()函数,

        mounted () {
        this.$store.dispatch('getShopInfo')
    // 如果数据还没有, 直接结束
          if(!this.info.pics) {
            return
          }
    
          // 数据有了, 可以创建BScroll对象形成滑动
          this._initScroll()
        },
    
        methods: {
          _initScroll () {
            new BScroll('.shop-info')
            // 动态计算ul的宽度
            const ul = this.$refs.picsUl
            const liWidth = 120
            const space = 6
            const count = this.info.pics.length
            ul.style.width = (liWidth + space) * count -space + 'px'
    
            new BScroll('.pic-wrapper', {
              scrollX: true // 水平滑动
            })
          }
        },
    
        watch: {
          info () {// 刷新流程--> 更新数据
            this.$nextTick(() => {
              this._initScroll()
            })
          }
        }

    三,搜索search页面搭建

     从vuex中获取搜索商家列表数据,需要传递搜索关键字

    当点击提交按钮(阻止form表单自己提交prevent),dispatch到vuex,获取数据

        <form class="search_form" @submit.prevent="search">
          <input type="search" placeholder="请输入商家名称" class="search_input" v-model="keyword">
          <input type="submit" class="search_submit">
        </form>
      methods:{
        search(){
          if(this.keyword.trim()){
            this.$store.dispatch('searchShops',this.keyword )
          }
          
        }
      },
    
      computed:{
        ...mapState(['searchShops'])
      }

     填充数据

    注,点击提交按钮时,当有数据的时候,显示数据,没有数据时,显示很抱歉!无搜索结果

    此时,出现一个小bug,当第一次search页面渲染时,没有点击提交按钮,还是显示很抱歉,无搜索结果,需要判断

    定义一个标识变量noSearchShops默认false,不显示数据。之后点击提交按钮,需要监视searchShops数据,有新数据,noSearchShops为false,  没有数据为

    true
    data() {
        return {
          keyword:'',
          imgBaseUrl: 'http://cangdu.org:8001/img/',
          noSearchShops:false
        }
      },
      watch: {
          // 监视searchShop数据
          searchShops (value) {
            if(!value.length) { // 没有数据
              this.noSearchShops = true
            } else {// 有数据
              this.noSearchShops = false
            }
          }
        },

    如果router-link被浏览器渲染时a标签,但是如果把它改成li标签,加一个tag属性

      <section class="list" v-if="!noSearchShops">
          <ul class="list_container">
           <!--:to="'/shop?id='+item.id"-->
            <router-link :to="{path:'/shop', query:{id:item.id}}" tag="li"
                         v-for="item in searchShops" :key="item.id" class="list_li">
              <section class="item_left">
                <img :src="imgBaseUrl + item.image_path" class="restaurant_img" style="50px">
              </section>
     
  • 相关阅读:
    mac下创建nativescript angular项目
    图解原型及原型链
    类型转换规则
    无符号右移操作符 this.length >>> 0
    认识 void 运算符
    Spark ML机器学习库评估指标示例
    CentOS7 Cloudera Manager6 完全离线安装 CDH6 集群
    Ambari HDP 下 SPARK2 与 Phoenix 整合
    IDEA设置
    Tricky Sum
  • 原文地址:https://www.cnblogs.com/fsg6/p/14342601.html
Copyright © 2020-2023  润新知