老师,这个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>
掌握Vue1.0到2.0再到2.5最全版本应用与迭代,打造极致流畅的WebApp
了解课程