请稍等 ...
×

采纳答案成功!

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

listShow问题,点击里面的加减号之前弹起的页面会折叠

老师,这个listShow不知道为什么我一点击它里面的增减food,它就会折叠,但是东西确实加了或者减了,但是页面也会折叠,按道理应该停在那里不折叠的。。
另外这个listShow用computed会有side effect,然后我用watch效果也是一样,也是点击listContent的加减号,然后页面会折叠,黄老师帮看看

 <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>
          <!-- v-show防止没有添加数量的时候显示这个红色小图标 -->
          <div class="num" v-show="totalCount > 0">{{ totalCount }}</div>
        </div>
        <!-- 总价 -->
        <div class="price" :class="{ highlight: totalPrice > 0 }">
          ¥{{ totalPrice }}
        </div>
        <!-- 运费的描述 -->
        <div class="desc">另需配送费¥{{ deliveryPrice }}元</div>
      </div>
      <div class="content-right">
        <div class="pay" :class="classObject">{{ payDesc }}</div>
      </div>
      <div class="ball-container">
        <div v-for="(ball, index) in balls" :key="index">
          <!-- transition only works for single element,it will generate error if put transition on  "<div v-for="(ball, index) in balls" :key="index">" -->
          <transition
            name="drop"
            @before-enter="beforeDrop"
            @enter="dropping"
            @after-enter="afterDrop"
          >
            <!-- show设为false,让小球一开始的状态影藏 -->
            <div v-show="ball.show" class="ball">
              <div class="inner inner-hook"></div>
            </div>
          </transition>
        </div>
      </div>
      <transition name="fold">
        <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) in selectFoods"
                :key="index"
              >
                <span class="name">{{ food.name }}</span>
                <div class="price">
                  <span>¥{{ food.price * food.count }}</span>
                </div>
                <div class="cartcontrol-wrapper">
                  <cartcontrol :food="food"></cartcontrol>
                </div>
              </li>
            </ul>
          </div>
        </div>
      </transition>
    </div>
  </div>
.shopcart
  position fixed
  left 0
  bottom 0
  z-index 50
  width 100%
  height 48px
  .content
    display flex
    background #141d27
    font-size 0px
    color: rgba(255, 255, 255, 0.4)
    .content-left
      flex 1
      .logo-wrapper
        display inline-block
        position relative
        vertical-align top
        top -10px
        margin 0 12px
        padding 6px
        width 56px
        height 56px
        box-sizing border-box
        border-radius 50%
        background #141d27
        .logo
          width 100%
          height 100%
          border-radius 50%
          text-align center
          background-color #2b343c
          &.highlight
            background rgb(0,160,220)
          .icon-shopping_cart
            line-height 44px
            font-size 24px
            color #80858a
            &.highlight
              color #fff
        .num
          position absolute
          top 0
          right 0
          width 24px
          height 16px
          line-height 16px
          text-align center
          border-radius 16px
          font-size 9px
          font-weight bold
          color #fff
          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 bold
        &.highlight
          color #fff
      .desc
        display inline-block
        vertical-align top
        line-height 24px
        margin 12px 0 0 12px
        font-size 12px
    .content-right
      flex 0 0 105px
      width 105px
      .pay
        height 48px
        line-height 48px
        text-align center
        font-size 12px
        &.not-enough
          background #2b333b
        &.enough
          background #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
      top 0
      left 0
      z-index -1
      width 100%
      transform translate3d(0,-100%,0)
      &.fold-enter-active, &.fold-leave-active
        transition: all 0.5s
      &.fold-enter, &.fold-leave-active
        transform: translate3d(0, 0, 0)
      .list-header
        height: 40px
        line-height: 40px
        padding: 0 18px
        background: #f3f5f7
        border-bottom: 1px solid rgba(7, 17, 27, 0.1)
        .title
          float: left
          font-size: 14px
          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 14px
            color rgb(7,17,27)
          .price
            position absolute
            right 90px
            bottom 12px
            line-height 24px
            font-size 14px
            font-weight bold
            color rgb(240,20,20)
          .cartcontrol-wrapper
            position absolute
            right 0
            bottom 6px
<script>
import Cartcontrol from 'components/cartcontrol/cartcontrol'
import BScroll from 'better-scroll'
export default {
  props: {
    deliveryPrice: {
      type: Number,
      default: 0,
    },
    minPrice: {
      type: Number,
      default: 0,
    },
    selectFoods: {
      type: Array,
      default() {
        return []
      },
    },
  },
  data() {
    return {
      balls: [
        { show: false },
        { show: false },
        { show: false },
        { show: false },
        { show: false },
      ],
      dropBalls: [],
      // 这个fold可以看做标志位
      fold: true,
    }
  },
  computed: {
    totalPrice() {
      let total = 0
      this.selectFoods.forEach((food) => {
        total += food.count * food.price
      })
      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 '去结算'
      }
    },
    classObject() {
      if (this.totalPrice < this.minPrice) {
        return 'not-enough'
      } else {
        return 'enough'
      }
    },
    listShow() {
      // 这里用计算属性会产生副作用,不推荐
      if (!this.totalCount) {
        // eslint-disable-next-line vue/no-side-effects-in-computed-properties
        this.fold = true
        return false
      }
      let show = !this.fold
      if (show) {
        this.$nextTick(() => {
          if (!this.scroll) {
            this.scroll = new BScroll(this.$refs.listContent, { click: true })
          } else {
            this.scroll.refresh()
          }
        })
      }
      return show
    },
  },
  methods: {
    // 把ball.show改为true然后进行显示
    drop(el) {
      for (let i = 0; i < this.balls.length; i++) {
        let ball = this.balls[i]
        if (!ball.show) {
          ball.show = true
          ball.el = el
          console.log(ball.el)
          this.dropBalls.push(ball)
          return
        }
      }
    },
    beforeDrop(el) {
      console.log(el)
      let count = this.balls.length
      while (count--) {
        let ball = this.balls[count]
        if (ball.show) {
          // Element.getBoundingClientRect() 方法返回元素的大小及其相对于视口的位置。
          // ball.el在这里有用,通过它拿到x,y的距离
          let rect = ball.el.getBoundingClientRect()
          // 32px是.ball的固定定位left:32px
          let x = rect.left - 32
          // 22px是.ball的固定定位bottom:22px
          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) {
        return
      }
      this.fold = !this.fold
    },
  },
  // watch: {
  //   totalCount() {
  //     if (!this.totalCount) {
  //       this.fold = false
  //     }
  //     if (!this.fold) {
  //       this.$nextTick(() => {
  //         if (!this.scroll) {
  //           this.scroll = new BScroll(this.$refs.listContent, { click: true })
  //         } else {
  //           this.scroll.refresh()
  //         }
  //       })
  //     }
  //   },
  // },不知道咋写,写错了自己用watch
  components: {
    cartcontrol: Cartcontrol,
  },
}
</script>

正在回答 回答被采纳积分+3

2回答

提问者 我要学习去了 2020-05-04 22:09:41

computed的listShow改成watch,希望对后面的学习者有帮助,后面v-show绑定fold这个标志位

data() {
   return {
   fold = false
   }
  }
  
  watch: {
    totalCount() {
      if (!this.totalCount) {
        this.fold = false
      }
      if (!this.fold) {
        this.$nextTick(() => {
          if (!this.scroll) {
            this.scroll = new BScroll(this.$refs.listContent, { click: true })
          } else {
            this.scroll.refresh()
          }
        })
      }
    },
  },


0 回复 有任何疑惑可以回复我~
ustbhuangyi 2020-05-04 19:48:05

副作用那块你可以把逻辑优化了,另外点击折叠应该是内层点击事件冒泡到外层了,你的 cart-control 加剪号的 click 事件有阻止冒泡吗?

0 回复 有任何疑惑可以回复我~
  • 提问者 我要学习去了 #1
    黄老师,不知道说啥好,厉害。。。非常感谢
    回复 有任何疑惑可以回复我~ 2020-05-04 20:16:36
  • 提问者 我要学习去了 #2
    花了六七个小时没解决的问题,你一下看出来了。。。
    回复 有任何疑惑可以回复我~ 2020-05-04 20:17:57
  • ustbhuangyi 回复 提问者 我要学习去了 #3
    建议你遇到问题的时候可以给你的代码加 debugger,然后看一下函数调用堆栈,很多问题就容易定位了
    回复 有任何疑惑可以回复我~ 2020-05-04 20:29:47
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信