shopcart.vue购物车

html代码

js代码

  import BScroll from 'better-scroll';
  import cartcontrol from '../../components/cartcontrol/cartcontrol';

  export default{
    props: {
      selectFoods: {
        type: Array,
        default(){ //data必须是一个函数,这是默认值data的写法
          return [ 
            {}
          ];
        }
      },
      deliveryPrice: { 
        type: Number,
        default: 0
      },
      minPrice: {
        type: Number,
        default: 0
      }
    },
    data(){
      return {
        fold: true //通过这个变量来控制隐藏和显示购物车列表,true代表隐藏,折叠起来
      }
    },
    computed: {
      totalPrice(){ //计算总价
        let total = 0;
        this.selectFoods.forEach((food) => {
          total += food.price * food.count; //这个count就是在goods组件里面添加的
        })
        return total;
      },
      totalCount(){ //计算总数量
        let count = 0;
        this.selectFoods.forEach((food) => {
          count += food.count;
        })
        return count;
      },
      payDesc(){ //只是简单的做一些支付显示的计算
        if (this.totalPrice === 0) {
          return `¥${this.minPrice}元起送`;
        } else if (this.totalPrice < this.minPrice) {
          let diff = this.minPrice - this.totalPrice;
          return `还差¥${diff}元配送`;
        } else {
          return `去结算`;
        }
      },
      payClass(){
        if (this.totalPrice < this.minPrice) {
          return 'not-enough';
        } else {
          return 'enough';
        }
      },
      listShow(){ //自动计算购物车列表是否显示和隐藏
        if (!this.totalCount) { //自动判断商品数量为空
          this.fold = true; //直接隐藏
          return false;
        }
        let show = !this.fold; //当flod为false的时候显示购物车列表
        if (show) { 
          this.$nextTick(() => { //异步执行滚动列表初始化
            if (!this.scroll) {
              this.scroll = new BScroll(this.$refs.listContent, {
                click: true
              });
            } else {
              this.scroll.refresh();
            }
          });
        }
        return show;
      }
    },
    methods: {
      toggleList(){
        if (!this.totalCount) {
          return;
        }
        this.fold = !this.fold;
      },
      empty() { //通过清空数据属性来控制购物车清空
        this.selectFoods.forEach((food) => {
          food.count = 0;
        });
      },
      hideList() {
        this.fold = true;
      },
      pay() {
        if (this.totalPrice < this.minPrice) {
          return;
        }
        window.alert(`支付${this.totalPrice}元`);
      }
    },
    components: {
      cartcontrol
    }
  }
  • 购物车列表的显示和隐藏(折叠)是通过数据fold来决定的,他是通过计算属性listshow来实现的,这样达到了不用操作dom就可以改变dom行为的效果,vue的数据驱动设计.

  • 清空按钮也是这样实现的,通过批量设置count属性来实现

  • 抛物线小球部分参考:关于购物车添加按钮的动画

  • 因为打开shopcart详情页会出现两个内容:

    • shopcart-list部分参考:八.shopcart-list购物车详情页

    • cartcontrol部分参考:cartcontrol.vue购物车操作按钮

    • 又因为这个cartcontrol是有几个地方都需要用到的,所以将其组件化处理

css代码

  @import "../../common/stylus/mixin.styl"

  .shopcart
    position: fixed //这是固定在页面底部的购物车栏目
    left: 0
    bottom: 0
    z-index: 50 
    width: 100%
    height: 48px
    .content
      display: flex //flex布局
      background: #141d27
      font-size: 0
      .content-left
        flex: 1
        .logo-wrapper
          display: inline-block
          position: relative
          top: -10px //因为要凸出购物车栏目一点点,设计需要
          margin: 0 12px
          padding: 6px
          width: 56px //因为使用了border-box的关系,可以直接写设计的尺寸
          height: 56px
          box-sizing: border-box //border-box可以省去计算border和内边距
          vertical-align: top
          border-radius: 50%
          background: #141d27
          .logo
            width: 100%
            height: 100%
            border-radius: 50%
            text-align: center
            background: #2b343c
            &.highlight
              background: rgb(0, 160, 220)
            .icon-shopping_cart
              line-height: 44px
              font-size: 24px
              color: #80858a
              &.highlight
                color: #ffffff
          .num
            position: absolute
            top: 0
            right: 0
            width: 24px
            height: 16px
            line-height: 16px
            text-align: center
            border-radius: 16px
            font-size: 9px
            color: #ffffff
            background: rgb(240, 20, 20)
            box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.4)
        .price
          display: inline-block
          vertical-align: top
          margin-top: 12px
          line-height: 24px
          padding-right: 12px
          box-sizing: border-box
          border-right: 1px solid rgba(255, 255, 255, 0.1)
          font-size: 16px
          font-weight: 700
          color: rgba(255, 255, 255, 0.4)
          &.highlight
            color: #ffffff
        .desc
          display: inline-block
          vertical-align: top
          margin: 12px 0 0 12px
          line-height: 24px
          color: rgba(255, 255, 255, 0.4)
          font-size: 10px
      .content-right
        flex: 0 0 105px //flex布局固定右边空间
        width: 105px
        .pay
          height: 48px
          line-height: 48px
          text-align: center
          font-size: 12px
          color: rgba(255, 255, 255, 0.4)
          font-weight: 700
          &.not-enough
            background: #2b333b
          &.enough
            background: #00b43c
            color: #ffffff
//省略了小球动画的css

  • 这里主要注意border-box的使用,举例logo-wrapper

    • 宽高都是56px,并且需要实现内边距是6px

    • 不用border-box的话,就要计算图片的区域是多大,然后加上6px内边距等于56px

    • 用了border-box的话,就不需要计算图片区域了,直接写56px,即使加上6px内边距也不撑大56px的区域,只会自动缩小内部图片区域的区域,实际情况就是外框区域56px,内边距6px,图片自动缩小到44px(6+44+6等于56)

你可能感兴趣的:(vue.js)