请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

购物车的加减号无法响应

图片描述

<template>
  <div class="cartcontroller">
    <transition name="move">
      <div class="cart-decrease" v-show="showDecrease" @click="decreaseCart">
        <i class="inner icon-remove_circle_outline"></i>
      </div>
    </transition>
    <div class="cart-count" v-show="showDecrease">{{this.food.count}}</div>
    <div class="cart-add" @click="addCart">
      <i class="icon-add_circle"></i>
    </div>
  </div>
</template>

<script>
import Vue from "vue";
export default {
  name: "CartController",
  props: {
    food: {
      type: Object
    }
  },
  components: {},
  data() {
    return {};
  },
  
  methods: {
    addCart(event) {
      if (!event._constructed) {
        return;
      }
      if (!this.food.count) {
        //查看Vue的文档发现,set可以在全局增加响应式视图需要的属性
        Vue.set(this.food, "count", 1);
        this.food.count = 1;
      } else {
        this.food.count += 1;
      }
      let _target = event.target;
      if (!_target.classList.contains("cart-add")) {
        _target = event.target.parentNode;
      }
      this.$emit("cart-add", _target);
    },
    decreaseCart(event) {
      if (!event._constructed) {
        return;
      }
      if (this.food.count) {
        this.food.count--;
      }
    }
  },
  computed: {
    showDecrease: function() {
      return this.food.count > 0;
    }
  }
};
</script>
<style lang="stylus" scoped>
.cartcontroller
  font-size: 0
  .cart-add
    display: inline-block
    padding: 6px
    line-height: 24px
    font-size: 24px
    color: rgb(0, 160, 220)
  .cart-decrease
    display: inline-block
    padding: 6px
    transition: all 0.5s linear
    .inner
      display: inline-block
      line-height: 24px
      font-size: 24px
      color: rgb(0, 160, 220)
    &.move-leave, &.move-enter-to
      opacity: 1
      transform: translate3d(0, 0, 0)
      .inner
        transform: rotate(0)
        transition: all 0.5s linear
    &.move-enter, &.move-leave-to
      opacity: 0
      transform: translate3d(48px, 0, 0)
      .inner
        transform: rotate(360deg)
        transition: all 0.5s linear
  .cart-count
    display: inline-block
    vertical-align: top
    width: 12px
    padding-top: 6px
    height: 24px
    line-height: 24px
    text-align: center
    font-size: 10px
    color: rgb(147, 153, 159)
</style>

下面是shopcar组件,调用上面的组件

<template>
  <div class="shopcart">
    <div class="content" @click="toggleList">
      <div class="content-left">
        <div class="logo-wrapper">
          <div class="logo" :class="{'highlight':totalCount>0}">
            <i class="icon-shopping_cart" :class="{'highlight':totalCount>0}"></i>
          </div>
          <div class="num" v-show="totalCount>0">{{totalCount}}</div>
        </div>
        <div class="price" :class="{'highlight':totalPrice>0}">¥{{totalPrice}}</div>
        <div class="desc">另需配送费¥{{seller.deliveryPrice}}元</div>
      </div>
      <div class="content-right">
        <div class="content-minPrice" :class="payClass">{{payDesc}}</div>
      </div>
    </div>
    <div class="ball-container">
      <div v-for="(ball,index) in balls" :key="index">
        <transition
          name="drop"
          @before-enter="beforeDrop"
          @enter="dropping"
          @after-enter="afterDrop"
        >
          <div class="ball" v-show="ball.show">
            <div class="inner inner-hook"></div>
          </div>
        </transition>
      </div>
    </div>
    <transition name="fold-cart">
      <div class="shopcart-list" v-show="listShow">
        <div class="list-header">
          <h1 class="title">购物车</h1>
          <span class="empty">清空</span>
        </div>
        <div class="list-content" ref="listContent">
          <ul>
            <li class="food" v-for="(food,index) of selectFoods" :key="index">
              <span class="name">{{food.name}}</span>
              <div class="price">
                <span>¥{{food.price*food.count}}</span>
              </div>
              <div class="cartcontrol-wrapper">
                <cart-controller :food="food"></cart-controller>
              </div>
            </li>
          </ul>
        </div>
      </div>
    </transition>
  </div>
</template>

<script>
import CartController from "../cartCtr/cartCtr";
import BScroll from "@better-scroll/core";
export default {
  name: "ShopCar",
  props: {
    seller: {
      type: Object
    },
    selectFoods: {
      type: Array,
      default() {
        return [
          {
            price: 0,
            count: 0
          }
        ];
      }
    }
  },
  components: {
    CartController
  },
  data() {
    return {
      balls: [
        {
          show: false
        },
        {
          show: false
        },
        {
          show: false
        },
        {
          show: false
        },
        {
          show: false
        }
      ],
      dropBalls: [],
      listShow: false
    };
  },
  methods: {
    drop: function(el) {
      for (let index = 0; index < this.balls.length; index++) {
        let ball = this.balls[index];
        if (!ball.show) {
          ball.show = true;
          ball.el = el;
          this.dropBalls.push(ball);
          return;
        }
      }
    },
    beforeDrop(el) {
      let count = this.balls.length;
      while (count--) {
        let ball = this.balls[count];
        if (ball.show) {
          let rect = ball.el.getBoundingClientRect();
          let x = rect.left - 32;
          let y = -(window.innerHeight - rect.top - 22);
          el.style.display = "";
          el.style.webkitTransform = `translate3d(0,${y}px,0)`;
          el.style.transform = `translate3d(0,${y}px,0)`;
          let inner = el.getElementsByClassName("inner-hook")[0];
          inner.style.webkitTransform = `translate3d(${x}px,0,0)`;
          inner.style.transform = `translate3d(${x}px,0,0)`;
        }
      }
    },
    dropping(el, done) {
      /* eslint-disable no-unused-vars */
      let rf = el.offsetHeight;
      this.$nextTick(() => {
        el.style.webkitTransform = "translate3d(0,0,0)";
        el.style.transform = "translate3d(0,0,0)";
        let inner = el.getElementsByClassName("inner-hook")[0];
        inner.style.webkitTransform = "translate3d(0,0,0)";
        inner.style.transform = "translate3d(0,0,0)";
        el.addEventListener("transitionend", done);
      });
    },
    afterDrop(el) {
      let ball = this.dropBalls.shift();
      if (ball) {
        ball.show = false;
        el.style.display = "none";
      }
    },
    toggleList() {
      if (this.totalCount > 0) {
        this.listShow = !this.listShow;
        if (this.listShow) {
          this._initScrollShopcart();
        }
      } else {
        return;
      }
    },
    _initScrollShopcart() {
      this.$nextTick(() => {
        this.scroll = new BScroll(this.$refs.listContent, {
          click: true,
          bounce: false,
          scrollbar: false,
          preventDefault: false,
          tap: true,
          mouseWheel: true
        });
      });
    }
  },
  computed: {
    totalPrice: function() {
      let total = 0;
      this.selectFoods.forEach(food => {
        total += food.price * food.count;
      });
      return total;
    },
    totalCount: function() {
      let count = 0;
      this.selectFoods.forEach(food => {
        count += food.count;
      });
      return count;
    },
    payDesc: function() {
      let minusPrice = this.totalPrice - this.seller.minPrice;
      if (this.totalPrice === 0) {
        return `¥${this.seller.minPrice}起送`;
      } else if (minusPrice > 0) {
        return "去结算";
      } else {
        return `还差¥${Math.abs(minusPrice)}起送`;
      }
    },
    payClass: function() {
      if (this.totalPrice < this.seller.minPrice) {
        return "not-enough";
      } else {
        return "enough";
      }
    }
  },
  watch: {
    totalCount: function() {
      if (this.totalCount <= 0) {
        this.listShow = false;
      }
      if (this.listShow && this.totalCount) {
        this._initScrollShopcart();
      }
    }
  }
};
</script>
<style lang="stylus" scoped>
@import './assets/common/mixin.styl'
.shopcart
  position: fixed
  left: 0
  bottom: 0
  width: 100%
  height: 48px
  z-index: 50
  .content
    display: flex
    height: 100%
    background: #141d27
    .content-left
      flex: 1
      .logo-wrapper
        display: inline-block
        position: relative
        top: -10px
        margin: 0 12px
        padding: 6px
        width: 56px
        height: 56px
        box-sizing: border-box
        vertical-align: top
        border-radius: 50%
        background: #141d27
        .logo
          height: 100%
          width: 100%
          border-radius: 50%
          background: #2B343C
          text-align: center
          &.highlight
            background: rgb(0, 160, 220)
          .icon-shopping_cart
            line-height: 44px
            font-size: 24px
            color: rgba(255, 255, 255, 0.4)
            &.highlight
              color: #fff
        .num
          position: absolute
          right: 0
          top: 0
          min-width: 24px
          height: 16px
          line-height: 16px
          border-radius: 16px
          background-color: rgb(240, 20, 20)
          text-align: center
          font-size: 9px
          font-weight: 700
          color: rgb(255, 255, 255)
          box-shadow: 0 4px 8px 0px rgba(0, 0, 0, 0.4)
      .price
        display: inline-block
        vertical-align: top
        margin-top: 12px
        padding-right: 12px
        line-height: 24px
        font-size: 16px
        color: rgba(255, 255, 255, 0.4)
        font-weight: 700
        box-sizing: border-box
        border-right: 1px solid rgba(255, 255, 255, 0.1)
        &.highlight
          color: #fff
      .desc
        display: inline-block
        vertical-align: top
        margin-top: 12px
        padding-left: 12px
        font-size: 16px
        color: rgba(255, 255, 255, 0.4)
        font-weight: 700
        line-height: 24px
    .content-right
      flex: 0 0 105px
      width: 105px
      background: #2B333B
      .content-minPrice
        line-height: 48px
        height: 48px
        text-align: center
        font-size: 12px
        color: rgba(255, 255, 255, 0.4)
        font-weight: 700
        &.not-enough
          background: #2b333b
        &.enough
          background-color: #00b43c
          color: #fff
  .ball-container
    .ball
      position: fixed
      left: 32px
      bottom: 22px
      z-index: 200
      transition: all 0.4s cubic-bezier(0.49, -0.29, 0.75, 0.41)
      .inner
        width: 16px
        height: 16px
        border-radius: 50%
        background: rgb(0, 160, 220)
        transition: all 0.4s linear
  .shopcart-list
    position: absolute
    left: 0
    bottom: 48px
    z-index: -1
    width: 100%
    &.fold-cart-enter
      transform: translate3d(0, 100%, 0)
    &.fold-cart-enter-to
      transition: all 0.8s ease-in-out
      transform: translate3d(0, 0, 0)
    &.fold-cart-leave
      transform: translate3d(0, 0, 0)
    &.fold-cart-leave-to
      transition: all 0.8s ease-in-out
      transform: translate3d(0, 100%, 0)
    .list-header
      height: 40px
      line-height: 40px
      padding: 0 18px
      background-color: #F3F5F7
      border-bottom: 1px solid rgba(7, 17, 27, 0.1)
      .title
        float: left
        font-size: 14px
        font-weight: 200
        color: rgb(7, 17, 27)
      .empty
        float: right
        font-size: 12px
        color: rgb(0, 160, 220)
    .list-content
      padding: 0 18px
      max-height: 217px
      overflow: hidden
      background: #fff
      .food
        position: relative
        padding: 12px 0
        box-sizing: border-box
        border-1px(rgba(7, 17, 27, 0.1))
        .name
          line-height: 24px
          font-size: 12px
          color: rgb(7, 17, 27)
        .price
          position: absolute
          right: 90px
          bottom: 12px
          line-height: 24px
          font-size: 14px
          font-weight: 700
          color: rgb(240, 20, 20)
        .cartcontrol-wrapper
          position: absolute
          right: 0
          bottom: 6px
</style>

this.scroll.refresh()不起作用,就只能每次都初始化自定义的_initScrollShopcart() 方法。

正在回答

6回答

你不需要用这么 hack 的方式,本质上是因为你多次 new BScroll 导致的,每次创建都会添加一次点击事件,所以解决方案如下:
https://img1.sycdn.imooc.com//szimg/5df7507f09c8f97513280732.jpg

1 回复 有任何疑惑可以回复我~
提问者 weixin_慕妹0008060 2019-12-16 15:50:12

老师,我发现一个最新的bug,我虽然解决了,但是感觉方法比较笨,问问老师有没有好的办法?

解决的办法如下:

https://img1.sycdn.imooc.com//szimg/5df7356d097187b703600146.jpg

https://img1.sycdn.imooc.com/szimg/5df7356e09ecdf6a04470185.jpg

https://img1.sycdn.imooc.com//szimg/5df7356e0950f75500000000.jpg

https://img1.sycdn.imooc.com//szimg/5df7346e0945a37700000000.jpg

bug如下:

https://img1.sycdn.imooc.com/szimg/5df733d6096cd37f04180421.jpg

bug具体描述:每次点击上述+、-号的时候,总是自动执行多次,点击事件总是自动执行多次。我的思路是能不能每次只在点击的时候,才让点击事件执行一次,不能多次执行。,于是想办法每次执行一次点击事件,就解绑一次点击事件,在下次点击的时候,又重新绑定一次点击事件。但是在vue中没有找到如何解绑点击事件的方法。


0 回复 有任何疑惑可以回复我~
ustbhuangyi 2019-12-16 13:37:21

https://img1.sycdn.imooc.com/szimg/5df717f509ebff6208380182.jpg
另外这个 - 号初始偏移位置 24px 为宜,防止初始状态快速双击导致 bug

0 回复 有任何疑惑可以回复我~
ustbhuangyi 2019-12-16 13:30:34

https://img1.sycdn.imooc.com/szimg/5df7165109c0790014620746.jpg
你这里的深拷贝是多余的,只会让你修改的对象引用不正确。
https://img1.sycdn.imooc.com//szimg/5df71671094ba3d004700124.jpg
goods 的初始化也有问题

0 回复 有任何疑惑可以回复我~
提问者 weixin_慕妹0008060 2019-12-16 12:27:51

https://img1.sycdn.imooc.com//szimg/5df707a0091045a204120565.jpg

具体如上

0 回复 有任何疑惑可以回复我~
ustbhuangyi 2019-12-16 10:54:42

你把代码传到 GitHub 上,我抽空帮你看一下

0 回复 有任何疑惑可以回复我~
  • 提问者 weixin_慕妹0008060 #1
    https://github.com/bangexe/elem-sell/tree/goods-shopcar
    看最新的分支--goods-shopcar
    回复 有任何疑惑可以回复我~ 2019-12-16 10:59:34
  • ustbhuangyi 回复 提问者 weixin_慕妹0008060 #2
    我运行你的代码,点加减号是有响应的呀。另外有个报错你处理一下吧,加个保护。
    回复 有任何疑惑可以回复我~ 2019-12-16 11:25:46
  • 提问者 weixin_慕妹0008060 回复 ustbhuangyi #3
    老师,我贴了最新的截图。我程序运行在chrome上,总是无法点击加减号。
    回复 有任何疑惑可以回复我~ 2019-12-16 12:28:59
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信