这里通过currentIndex和index做对比,来确认是否添加current类,通过添加current类来实现当前页面的区域的样式变化,他们之间的对比关系也就是menu区域和foods区域的显示区域的对比关系
需要注意的是vue传递原生事件使用$event
<script> import BScroll from 'better-scroll' import cartcontrol from './cartcontrol' import submitBar from './submitBar' import { mapGetters } from 'vuex' export default { name: 'takeout', data() { return { goods: [], listHeight: [], scrollY: 0 } }, components: { cartcontrol, submitBar }, computed: { ...mapGetters([ 'showTakeout' ]), currentIndex () { for(let i = 0; i < this.listHeight.length; i++) { let height1 = this.listHeight[i - 1] let height2 = this.listHeight[i] if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) { return i } } return 0 }, selectFoods () { let foods = [] this.goods.forEach(good => { good.foods.forEach(food => { if (food.count) { foods.push(food) } }) }) return foods } }, methods: { backTo () { this.$store.dispatch('setShowTakeout', false) }, selectMenu(index, event) { if (!event._constructed) { return; } let foodList = this.$refs.foodList; let el = foodList[index]; this.foodsScroll.scrollToElement(el, 300); }, selectFood(food, event) { if (!event._constructed) { return; } this.selectedFood = food; }, _initScroll() { this.meunScroll = new BScroll(this.$refs.menuWrapper, { click: true }) this.foodsScroll = new BScroll(this.$refs.foodsWrapper, { click: true, probeType: 3 }) this.foodsScroll.on('scroll', pos => { this.scrollY = Math.abs(Math.round(pos.y)) }) }, _calculateHeight () { let foodList = this.$refs.foodList let height = 0 for (let i = 0; i < foodList.length; i++) { let item = foodList[i] height += item.clientHeight this.listHeight.push(height) } }, }, created () { this.$http.get('https://www.easy-mock.com/mock/5ca49494ea0dc52bf3b67f4e/example/takeout') .then(res => { if (res.data.errno === 0) { this.goods = res.data.data this.$nextTick(() => { this._initScroll() this._calculateHeight() }) } }) } } </script>
购物车
<template> <div> <van-submit-bar :loading="setloading" :price="totalPrice" button-text="提交订单" @submit="onSubmit" > <div @click="toggleList"> <img src="" alt=""> <span v-if="selectFoods.length > 0">{{selectFoods.length}}</span> </div> </van-submit-bar> <transition> <div v-show="listShow"> <div> <h1>购物车</h1> <span @click="empty">清空</span> </div> <div ref="listContent"> <ul> <li v-for="(food, index) in selectFoods" :key="index"> <span>{{food.name}}</span> <div> <span>¥{{food.price*food.count}}</span> </div> <div> <cartcontrol @add="addFood" :food="food"></cartcontrol> </div> </li> </ul> </div> </div> </transition> <transition> <div @click="hideList" v-show="listShow"></div> </transition> </div> </template>
购物车列表的显示和隐藏以及清空按钮是通过数据fold来决定的,购物车列表是通过计算属性listshow来实现,清空按钮也是通过设置count属性来实现,这样都达到了不用操作dom就可以改变dom行为的效果。
<script> import { SubmitBar } from 'vant'; import BScroll from 'better-scroll'; import cartcontrol from './cartcontrol'; export default { props: { selectFoods: { type: Array, default() { return [ { price: 10, count: 1 } ] } }, }, data() { return { setloading: false, fold: true } }, computed: { totalCount () { let count = 0 this.selectFoods.forEach((food) => { count += food.count }) return count }, totalPrice () { let total = 0 this.selectFoods.forEach((food) => { total += food.price * food.count * 100 }) return total }, listShow () { if (!this.totalCount) { 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: { toggleList(){ console.log(this.totalCount) if (!this.totalCount) { return; } this.fold = !this.fold; }, onSubmit() { this.setloading = true }, empty() { this.selectFoods.forEach((food) => { food.count = 0; }); }, hideList() { this.fold = true; }, addFood() {} }, components: { cartcontrol } } </script>
操作按钮
这个模块主要通过三个小模块实现,删除按钮,显示数量块,增加按钮
<template> <div> <transition> <div v-show="food.count > 0" @click="decreaseCart"> <div> <img src="" alt=""> </div> </div> </transition> <div v-show="food.count > 0">{{food.count}}</div> <div @click="addCart"> <img src="" alt=""> </div> </div> </template>