12.加入购物车

思路:

  • 1.点击加入购物车,需要判断用户的登录状态(先前端校验,再接口后端校验)

  • 2.调用加入购物车的接口,完成

    • 1.如果购物车中有这个产品,更新购物车,数量加1即可

    • 2.如果购物车中没有这个产品,插入一条记录即可

  • 前端可以通过 loginState 校验登录

  • 后端通过前端传递的 token 校验登录状态

// src/api/cart.js
import request from '../utils/request'
​
// 加入购物车
export function addCart (params) {return request.post('/cart/add', params)
}
// 获取购物车数据
export function getCartList (params) {return request.post('/cart/list', params)
}
// 删除当前用户的所有的购物车中的数据
export function removeAll (params) {return request.post('/cart/removeall', params)
}
// 删除购物车中的单条数据
export function remove (params) {return request.post('/cart/remove', params)
}
​
// 更新购物车中的单条数据的复选框的 选中状态
export function selectOne (params) {return request.post('/cart/selectone', params)
}
​
// 更新购物车中的全选的选中状态
export function selectAll (params) {return request.post('/cart/selectall', params)
}
​
// 更新购物车单条数据的数量
export function updateNum (params) {return request.post('/cart/updatenum', params)
}
​

12.1 封装axios 拦截器

axios中文文档|axios中文网 | axios

请求拦截器:给所有的请求的头信息中携带token信息

响应拦截器:先判断token的有效性,如果失效 直接跳转至登录页面

s r c/utils/request.js

import axios from 'axios'
import router from '../router' // +++++++++++++++++++
// 自定义axios
// const ins = axios.create({
//   // baseURL 以后调用接口可以不用写这个,程序会自动拼接
//   baseURL: 'http://121.89.205.189:3001/api',
//   timeout: 6000 // 请求的超时时间
// })
​
// 环境 - 开发环境 | 测试环境 | 生产环境
//       localhost |  ip地址  |  域名
//      yarn serve | yarn build  | yarn build
//      development |       |  production
// process 属于nodejs自带的一个全局的模块 ---- 进程
// http://nodejs.cn/api/process.html#processenv
// process.env ---- 判断环境
// process.env 本身并没有 NODE_ENV 这个变量,程序脚手架设置的 -- webpack 设置
const isDev = process.env.NODE_ENV === 'development' // 判断当前的运行环境的
​
const ins = axios.create({baseURL: isDev ? 'http://121.89.205.189:3001/api' : 'http://121.89.205.189:3001/api',timeout: 6000 // 请求的超时时间
})
​
// 请求拦截器
ins.interceptors.request.use((config) => {// 比如登录的验证 - tokenconfig.headers.token = localStorage.getItem('token') // +++++++++++++++++++return config
}, (error) => {return Promise.reject(error)
})
​
// 响应拦截器
ins.interceptors.response.use((response) => {// 验证登录,如果验证不通过,可以跳转到登录页面,验证通过,返回想要的数据if (response.data.code === '10119') { // +++++++++++++++++++// 后端校验登录状态 失败,需要跳转至 登录页面router.push('/login')return response}return response
}, (error) => {return Promise.reject(error)
})
​
export default ins
​

12.2 加入购物车

Src/views/detail/index.vue

<template><div class="box"><header class="header"><van-nav-barv-if="scrollTop < 50"left-arrow@click-left="$router.back()"><template #right><van-popoverv-model="showPopover"trigger="click"placement="bottom-end"theme="dark":actions="actions"@select="onSelect"><template #reference><van-icon name="ellipsis" size="32"/></template></van-popover></template></van-nav-bar><transition name="fade"><van-nav-barv-if="scrollTop >= 50":title="proname"left-arrow@click-left="$router.back()"><template #right><van-popoverv-model="showPopover"trigger="click"placement="bottom-end"theme="dark":actions="actions"@select="onSelect"><template #reference><van-icon name="ellipsis" size="32"/></template></van-popover></template></van-nav-bar></transition></header><div class="content" ref="content"><div class="my-detail-swiper"><van-swipe :show-indicators = "false" @change="changeSwiper" :initial-swipe="index - 1"><van-swipe-item v-for="(item, index) of banners" :key="index" @click="previewImage"><van-image  fit="scale-down" :src="item" /></van-swipe-item></van-swipe><div class="my-indicators">{{ index }} / {{ banners.length }}</div><div class="video-btn" @click="show = true"><van-icon name="play-circle-o" size="18" color="#f66"/> {{ time | timeFilter }}</div></div><div class="proname"><van-tag type="danger">{{ category }}</van-tag> {{ proname }}</div><div class="price">¥{{ discount !== 0 ? originprice * discount / 10 : originprice}}<del>¥{{ originprice }}</del></div>
​<div class="space">1111</div><van-goods-action  v-if="issale === 0"><van-goods-action-icon icon="chat-o" text="客服" color="#ee0a24" @click="chat"/><van-goods-action-icon icon="cart-o" text="购物车" /><van-goods-action-button type="warning" disabled text="商品已下架" /></van-goods-action><van-goods-action v-else><van-goods-action-icon icon="chat-o" text="客服" color="#ee0a24" @click="chat"/><van-goods-action-icon icon="cart-o" text="购物车" @click="toCart"/><van-goods-action-button type="warning" text="加入购物车" @click="addCartFn"/><van-goods-action-button type="danger" text="立即购买" /></van-goods-action>
​</div><van-share-sheetv-model="showShare"title="立即分享给好友":options="options"/><van-overlay :show="show" @click="show = false"><video controls class="my-video" ref="vdo" :src="vdoSrc"></video></van-overlay></div>
</template>
​
<script>
import Vue from 'vue'
import { Toast, Tag, NavBar, Popover, ShareSheet, Icon, Swipe, SwipeItem, Image as VanImage, ImagePreview, Overlay, GoodsAction, GoodsActionIcon, GoodsActionButton } from 'vant'
import { getProDetailData } from './../../api/detail'
import { addCart } from './../../api/cart'
Vue.use(Toast)
Vue.use(Tag)
Vue.use(NavBar)
Vue.use(Popover)
Vue.use(ShareSheet)
Vue.use(Icon)
Vue.use(Swipe)
Vue.use(SwipeItem)
Vue.use(VanImage)
Vue.use(ImagePreview)
Vue.use(Overlay)
Vue.use(GoodsAction)
Vue.use(GoodsActionIcon)
Vue.use(GoodsActionButton)
export default {data () {return {showPopover: false,// 通过 actions 属性来定义菜单选项 <van-icon name="location-o" />actions: [{ index: 0, text: '首页', icon: 'location-o' },{ index: 1, text: '分类', icon: 'like-o' },{ index: 2, text: '购物车', icon: 'shopping-cart-o' },{ index: 3, text: '个人中心', icon: 'friends-o' },{ index: 4, text: '分享', icon: 'share-o' }],showShare: false, // 分享面板options: [{ name: '微信', icon: 'wechat' },{ name: '微博', icon: 'weibo' },{ name: '复制链接', icon: 'link' },{ name: '分享海报', icon: 'poster' },{ name: '二维码', icon: 'qrcode' }],proid: '',banners: [], // 轮播图数据proname: '', // 产品名称originprice: 0, // 原价category: '', // 分类discount: 0, // 折扣issale: 0, // 是否在售卖index: 1,show: false, // 视频播放器vdoSrc: 'https://vod.300hu.com/4c1f7a6atransbjngwcloud1oss/2f9ff93e332543321040232449/v.f20.mp4?dockingId=dd606c09-5aa5-449d-9faa-442ac07456f2&storageSource=3',// vdoSrc: 'https://jvod.300hu.com/vod/product/c3cf94d5-6fb9-4354-9f18-cc01c19350ff/f98fc5d1f64d40b2b667940ebc36bae3.mp4',time: 0, // 视频的播放时长scrollTop: 0}},mounted () {const proid = this.$route.params.proidgetProDetailData(proid).then(res => {console.log(res.data.data)const banners = res.data.data.banners[0]this.proid = proidthis.banners = banners.split(',') // 特殊处理,并不是所有项目都需要this.proname = res.data.data.pronamethis.originprice = res.data.data.originpricethis.category = res.data.data.categorythis.discount = res.data.data.discountthis.issale = res.data.data.issaleconsole.log(this.$refs.vdo.duration)})setTimeout(() => {this.time = this.$refs.vdo.duration // 计算视频的总时长}, 1000)this.$refs.content.addEventListener('scroll', () => {this.scrollTop = this.$refs.content.scrollTop}, false)},filters: {timeFilter (val) { // 过滤器处理时间显示格式let a = Math.floor(val / 60)let b = Math.floor(val % 60)a = a < 10 ? '0' + a : ab = b < 10 ? '0' + b : breturn a + '‘' + b}},methods: {toCart () {this.$router.push('/cart')},addCartFn () {// 加入购物车const userid = localStorage.getItem('userid')const loginState = localStorage.getItem('loginState') === 'true'if (loginState) {// 前端校验为登录状态,接下来后端校验addCart({userid,proid: this.proid,num: 1}).then(res => {if (res.data.code !== '10119') {Toast('加入购物车数据')}})} else {// 前端校验为未登录状态this.$router.push('/login')}},chat () {window._MEIQIA('metadata', {name: '张津曦', // 美洽默认字段address: '吧啦吧啦吧啦', // 美洽默认字段sex: '男', // 自定义字段hobby: '女' // 自定义字段})window._MEIQIA('showPanel')},previewImage () {ImagePreview({images: this.banners,startPosition: this.index - 1,onChange: (index) => {console.log('111', index)this.index = index + 1}})},changeSwiper (index) {this.index = index + 1},onSelect ({ index }) {switch (index) {case 0:this.$router.push('/home')breakcase 1:this.$router.push('/kind')breakcase 2:this.$router.push('/cart')breakcase 3:this.$router.push('/user')breakcase 4:this.showShare = true}}},watch: {show (newVal) { // 监听视频播放if (newVal) {this.$refs.vdo.currentTime = 0 // 播放时长为0this.$refs.vdo.play()} else {this.$refs.vdo.pause()}// newVal ? this.$refs.vdo.play() : this.$refs.vdo.pause()}}
}
</script>
​
<style lang="stylus" scoped>
.van-swipeheight 3.3rembackground-color #fff.van-swipe-itemwidth 100%.van-imagewidth 100%imgwidth 100%
.my-detail-swiperposition relative.my-indicatorsposition absolutebottom 20pxright 0width 50pxheight 20pxbackground-color #cccctext-align  centerline-height 20pxborder-radius 10px 0 0 10px.video-btnposition absolutebottom 20pxleft 50%transform translateX(-50%)width 83pxheight 30pxbackground-color #ffffffborder-radius 30pxdisplay flexjustify-content centeralign-items center
.my-videoposition fixedwidth 100%top 50%transform translateY(-50%)
.pronamepadding 5px 10pxfont-size 16pxfont-weight bold
.pricecolor #ff6666delcolor #999
.spaceheight 1000px
.container .box .headerbackground-color transparent
.fade-enter-active{transition: opacity .5s;
}
.fade-leave-active {transition: opacity 0s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {opacity: 0;
}
</style>
​

12.3 查看购物车

查看购物车,必须得是登录状态,如果是为登录状态,点击购物车直接跳转到登录页面

如果是登录状态,没有请求到数据,显示购物车空空如也

如果有数据,展示购物车的数据

<template><div class="box"><header class="header"><van-nav-bartitle="登录"left-arrow@click-left="$router.back()"/></header><div class="content"><div class="noShop" v-if="flag"><van-empty description="购物车空空如也"><van-button @click="$router.push('/kind')" round type="danger" class="bottom-button">立即购物</van-button></van-empty></div><div v-else class="hasShop"><van-swipe-cellv-for="item of cartList":key="item.cartid"><van-card:num="item.num":price="item.originprice":title="item.proname":thumb="item.img1"><template #num><van-stepper v-model="item.num" theme="round"/></template></van-card><template #right><van-button square type="danger" text="删除" class="delete-button"/></template></van-swipe-cell>
​<van-submit-bar :price="3050" button-text="提交订单" @submit="onSubmit"><van-checkbox v-model="checked">全选</van-checkbox></van-submit-bar></div></div></div>
</template>
​
<script>
import Vue from 'vue'
import { NavBar, Empty, Button, Card, Stepper, SubmitBar, Checkbox, SwipeCell } from 'vant'
import { getCartList } from './../../api/cart'
Vue.use(NavBar)
Vue.use(Empty)
Vue.use(Button)
Vue.use(Card)
Vue.use(Stepper)
Vue.use(SubmitBar)
Vue.use(Checkbox)
Vue.use(SwipeCell)
export default {data () {return {cartList: [],flag: true,checked: false}},methods: {onSubmit () {}},mounted () {if (localStorage.getItem('isLogin') === 'true') {getCartList({ userid: localStorage.getItem('userid') }).then(res => {console.log(res.data)if (res.data.code === '10020') {this.flag = true} else {this.flag = falsethis.cartList = res.data.data}})} else {this.$router.push('/login')}}
}
</script>
​
<style lang="stylus" scoped>
.delete-button {height: 100%;
}
</style>
​

完善购物车页面(删除,修改数量,提示信息,底部的提交订单栏)

<template><div class="box"><header class="header"><van-nav-bartitle = '购物车'left-arrow@click-left="$router.back()"></van-nav-bar></header><div class="content"><div class="npShop" v-if="empty"><van-empty description="购物车空空如也"><van-button round type="danger" class="bottom-button">立即购物</van-button></van-empty></div><div class="shop" v-else><van-notice-barmode="closeable"left-icon="volume-o"text="亲爱的用户,像左滑动视图可以展示删除按钮,祝您在嗨购商场中购物愉快"/><van-swipe-cellv-for="item of cartList":key="item.cartid"><van-card:price="item.originprice":title="item.proname":thumb="item.img1"><template #num><van-stepper v-model="item.num" theme="round" button-size="22"/></template></van-card><template #right><van-button square text="删除" type="danger" class="delete-button" /></template></van-swipe-cell><van-submit-bar :price="3050" button-text="提交订单" @submit="onSubmit"><van-checkbox v-model="checked">全选</van-checkbox></van-submit-bar></div></div></div>
</template>
<script>
import Vue from 'vue'
import { NavBar, Empty, Button, Card, Stepper, SwipeCell, NoticeBar, SubmitBar, Checkbox } from 'vant'
import { getCartList } from '../../api/cart'
Vue.use(NavBar)
Vue.use(Empty)
Vue.use(Button)
Vue.use(Card)
Vue.use(Stepper)
Vue.use(SwipeCell)
Vue.use(NoticeBar)
Vue.use(SubmitBar)
Vue.use(Checkbox)
export default {data () {return {empty: true,cartList: [],checked: false // 全选}},computed: {},methods: {onSubmit () {console.log('提交订单')},getCartListData () {getCartList({userid: localStorage.getItem('userid')}).then(res => {console.log(res.data)if (res.data.code === '10020') {this.empty = true} else {this.empty = falsethis.cartList = res.data.data}})}},mounted () {if (localStorage.getItem('loginState') === 'true') {// 前端校验为登录状体啊this.getCartListData()} else {this.$router.push('/login')}}
}
</script>
​
<style lang="stylus">
.delete-buttonheight 100%
</style>
​

12.4 删除数据

<template><div class="box"><header class="header"><van-nav-bartitle = '购物车'left-arrow@click-left="$router.back()"></van-nav-bar></header><div class="content"><div class="npShop" v-if="empty"><van-empty description="购物车空空如也"><van-button round type="danger" class="bottom-button">立即购物</van-button></van-empty></div><div class="shop" v-else><van-notice-barmode="closeable"left-icon="volume-o"text="亲爱的用户,像左滑动视图可以展示删除按钮,祝您在嗨购商场中购物愉快"/><van-swipe-cellv-for="item of cartList":key="item.cartid"><van-card:price="item.originprice":title="item.proname":thumb="item.img1"><template #num><van-stepper v-model="item.num" theme="round" button-size="22"/></template></van-card><template #right><van-button square text="删除" type="danger" class="delete-button" @click="deleteCart(item.cartid)"/></template></van-swipe-cell><van-submit-bar :price="3050" button-text="提交订单" @submit="onSubmit"><van-checkbox v-model="checked">全选</van-checkbox></van-submit-bar></div></div></div>
</template>
<script>
import Vue from 'vue'
import { NavBar, Empty, Button, Card, Stepper, SwipeCell, NoticeBar, SubmitBar, Checkbox } from 'vant'
import { getCartList, remove } from '../../api/cart'
Vue.use(NavBar)
Vue.use(Empty)
Vue.use(Button)
Vue.use(Card)
Vue.use(Stepper)
Vue.use(SwipeCell)
Vue.use(NoticeBar)
Vue.use(SubmitBar)
Vue.use(Checkbox)
export default {data () {return {empty: true,cartList: [],checked: false // 全选}},computed: {},methods: {onSubmit () {console.log('提交订单')},deleteCart (cartid) {remove({ cartid }).then(() => this.getCartListData())},getCartListData () {getCartList({userid: localStorage.getItem('userid')}).then(res => {console.log(res.data)if (res.data.code === '10020') {this.empty = true} else {this.empty = falsethis.cartList = res.data.data}})}},mounted () {if (localStorage.getItem('loginState') === 'true') {// 前端校验为登录状体啊this.getCartListData()} else {this.$router.push('/login')}}
}
</script>
​
<style lang="stylus">
.delete-buttonheight 100%
</style>
​

12.5 计算总价和总数量

<template><div class="box"><header class="header"><van-nav-bar:title = 'totalNum > 0 ? "购物车-" + totalNum : "购物车"'left-arrow@click-left="$router.back()"></van-nav-bar></header><div class="content"><div class="npShop" v-if="empty"><van-empty description="购物车空空如也"><van-button round type="danger" class="bottom-button">立即购物</van-button></van-empty></div><div class="shop" v-else><van-notice-barmode="closeable"left-icon="volume-o"text="亲爱的用户,像左滑动视图可以展示删除按钮,祝您在嗨购商场中购物愉快"/><van-swipe-cellv-for="item of cartList":key="item.cartid"><van-card:price="item.originprice":title="item.proname":thumb="item.img1"><template #num><van-stepper v-model="item.num" theme="round" button-size="22"/></template></van-card><template #right><van-button square text="删除" type="danger" class="delete-button" @click="deleteCart(item.cartid)"/></template></van-swipe-cell><van-submit-bar :price="totalPrice" button-text="提交订单" @submit="onSubmit"><van-checkbox v-model="checked">全选</van-checkbox></van-submit-bar></div></div></div>
</template>
<script>
import Vue from 'vue'
import { NavBar, Empty, Button, Card, Stepper, SwipeCell, NoticeBar, SubmitBar, Checkbox } from 'vant'
import { getCartList, remove } from '../../api/cart'
Vue.use(NavBar)
Vue.use(Empty)
Vue.use(Button)
Vue.use(Card)
Vue.use(Stepper)
Vue.use(SwipeCell)
Vue.use(NoticeBar)
Vue.use(SubmitBar)
Vue.use(Checkbox)
export default {data () {return {empty: true,cartList: [],checked: false // 全选}},computed: {totalNum () {return this.cartList.reduce((sum, item) => {return sum + item.num}, 0)},totalPrice () {return this.cartList.reduce((sum, item) => {return sum + item.num * item.originprice}, 0) * 100}},methods: {onSubmit () {console.log('提交订单')},deleteCart (cartid) {remove({ cartid }).then(() => this.getCartListData())},getCartListData () {getCartList({userid: localStorage.getItem('userid')}).then(res => {console.log(res.data)if (res.data.code === '10020') {this.empty = truethis.cartList = [] // 临界值变化 - 否则删除完所有的商品,商品总数量有问题} else {this.empty = falsethis.cartList = res.data.data}})}},mounted () {if (localStorage.getItem('loginState') === 'true') {// 前端校验为登录状体啊this.getCartListData()} else {this.$router.push('/login')}}
}
</script>
​
<style lang="stylus">
.delete-buttonheight 100%
</style>
​

12.6 更新数量

<template><div class="box"><header class="header"><van-nav-bar:title = 'totalNum > 0 ? "购物车-" + totalNum : "购物车"'left-arrow@click-left="$router.back()"></van-nav-bar></header><div class="content"><div class="npShop" v-if="empty"><van-empty description="购物车空空如也"><van-button round type="danger" class="bottom-button">立即购物</van-button></van-empty></div><div class="shop" v-else><van-notice-barmode="closeable"left-icon="volume-o"text="亲爱的用户,像左滑动视图可以展示删除按钮,祝您在嗨购商场中购物愉快"/><van-swipe-cellv-for="item of cartList":key="item.cartid"><van-card:price="item.originprice":title="item.proname":thumb="item.img1"><template #num><van-stepper v-model="item.num" theme="round" button-size="22" @change="updateCartNum(item.num, item.cartid)"/></template></van-card><template #right><van-button square text="删除" type="danger" class="delete-button" @click="deleteCart(item.cartid)"/></template></van-swipe-cell><van-submit-bar :price="totalPrice" button-text="提交订单" @submit="onSubmit"><van-checkbox v-model="checked">全选</van-checkbox></van-submit-bar></div></div></div>
</template>
<script>
import Vue from 'vue'
import { NavBar, Empty, Button, Card, Stepper, SwipeCell, NoticeBar, SubmitBar, Checkbox } from 'vant'
import { getCartList, remove, updateNum } from '../../api/cart'
Vue.use(NavBar)
Vue.use(Empty)
Vue.use(Button)
Vue.use(Card)
Vue.use(Stepper)
Vue.use(SwipeCell)
Vue.use(NoticeBar)
Vue.use(SubmitBar)
Vue.use(Checkbox)
export default {data () {return {empty: true,cartList: [],checked: false // 全选}},computed: {totalNum () {return this.cartList.reduce((sum, item) => {return sum + item.num}, 0)},totalPrice () {return this.cartList.reduce((sum, item) => {return sum + item.num * item.originprice}, 0) * 100}},methods: {onSubmit () {console.log('提交订单')},deleteCart (cartid) {remove({ cartid }).then(() => this.getCartListData())},updateCartNum (num, cartid) {console.log(num, cartid)updateNum({num, cartid}).then(() => this.getCartListData())},getCartListData () {getCartList({userid: localStorage.getItem('userid')}).then(res => {console.log(res.data)if (res.data.code === '10020') {this.empty = truethis.cartList = [] // 临界值变化 - 否则删除完所有的商品,商品总数量有问题} else {this.empty = falsethis.cartList = res.data.data}})}},mounted () {if (localStorage.getItem('loginState') === 'true') {// 前端校验为登录状体啊this.getCartListData()} else {this.$router.push('/login')}}
}
</script>
​
<style lang="stylus">
.delete-buttonheight 100%
</style>
​

12.7全选

什么时候出现全选

使用change事件还是click事件

全选选中,列表所有的都要被选中,全选不选中,列表所有的都不被选中

列表当前数据没有被选中,全选一定不被选中,当前被选中,监测其余的有没有被选中,如果全被选中,全选一定被选中

建议使用click事件,因为change事件是数据的双向绑定

当前项没有被选中,全选一定没有被选中,就会触发一次change事件,而此时全选是没有被选中的,就会更改让所有的数据都没有被选中

12.8单选

12.9 计算选中的总价和总数量

只有选中的商品才会被计算总价和总数量

<template><div class="box"><header class="header"><van-nav-bar:title = 'totalNum > 0 ? "购物车-" + totalNum : "购物车"'left-arrow@click-left="$router.back()"></van-nav-bar></header><div class="content"><div class="npShop" v-if="empty"><van-empty description="购物车空空如也"><van-button round type="danger" class="bottom-button">立即购物</van-button></van-empty></div><div class="shop" v-else><van-notice-barmode="closeable"left-icon="volume-o"text="亲爱的用户,像左滑动视图可以展示删除按钮,祝您在嗨购商场中购物愉快"/><van-swipe-cellv-for="item of cartList":key="item.cartid"><van-row><van-col span="2"><div class="my-checkbox"><van-checkbox v-model="item.flag" @change="chooseOne(item.cartid, item.flag)"></van-checkbox></div></van-col><van-col span="22"><van-card:price="item.originprice":title="item.proname":thumb="item.img1"><template #num><van-stepper v-model="item.num" theme="round" button-size="22" @change="updateCartNum(item.num, item.cartid)"/></template></van-card></van-col></van-row>
​<template #right><van-button square text="删除" type="danger" class="delete-button" @click="deleteCart(item.cartid)"/></template></van-swipe-cell><van-submit-bar :price="totalPrice" button-text="提交订单" @submit="onSubmit"><van-checkbox v-model="checked" @click="chooseAll">全选</van-checkbox></van-submit-bar></div></div></div>
</template>
<script>
import Vue from 'vue'
import { NavBar, Empty, Button, Card, Stepper, SwipeCell, NoticeBar, SubmitBar, Checkbox, Col, Row } from 'vant'
import { getCartList, remove, updateNum, selectAll, selectOne } from '../../api/cart'
Vue.use(NavBar)
Vue.use(Empty)
Vue.use(Button)
Vue.use(Card)
Vue.use(Stepper)
Vue.use(SwipeCell)
Vue.use(NoticeBar)
Vue.use(SubmitBar)
Vue.use(Checkbox)
Vue.use(Col)
Vue.use(Row)
export default {data () {return {empty: true,cartList: [],checked: false // 全选}},computed: {totalNum () {return this.cartList.reduce((sum, item) => {return item.flag ? sum + item.num : sum + 0}, 0)},totalPrice () {return this.cartList.reduce((sum, item) => {return item.flag ? sum + item.num * item.originprice : sum + 0}, 0) * 100}},methods: {onSubmit () {console.log('提交订单')},chooseOne (cartid, flag) {console.log(cartid, flag)selectOne({ cartid, flag }).then(() => this.getCartListData())},chooseAll () {selectAll({userid: localStorage.getItem('userid'),type: this.checked // 数据的双向绑定}).then(() => this.getCartListData())},deleteCart (cartid) {remove({ cartid }).then(() => this.getCartListData())},updateCartNum (num, cartid) {console.log(num, cartid)updateNum({num, cartid}).then(() => this.getCartListData())},getCartListData () {getCartList({userid: localStorage.getItem('userid')}).then(res => {console.log(res.data)if (res.data.code === '10020') {this.empty = truethis.cartList = [] // 临界值变化 - 否则删除完所有的商品,商品总数量有问题} else {this.empty = falsethis.cartList = res.data.data// 判断全选的状态this.checked = this.cartList.every(item => item.flag)}})}},mounted () {if (localStorage.getItem('loginState') === 'true') {// 前端校验为登录状体啊this.getCartListData()} else {this.$router.push('/login')}}
}
</script>
​
<style lang="stylus">
.delete-buttonheight 100%
.my-checkboxheight 1.04rembackground-color #fffdisplay flexjustify-content centeralign-items center
</style>
​

12.10猜你喜欢

// src/api/cart.js
// 猜你喜欢数据
export function getRecommendList (params) {return request.get('/pro/recommendlist', params)
}
<template><div class="box"><header class="header"><van-nav-bar:title = 'totalNum > 0 ? "购物车-" + totalNum : "购物车"'left-arrow@click-left="$router.back()"></van-nav-bar></header><div class="content"><div class="npShop" v-if="empty"><van-empty description="购物车空空如也"><van-button round type="danger" class="bottom-button">立即购物</van-button></van-empty></div><div class="shop" v-else><van-notice-barmode="closeable"left-icon="volume-o"text="亲爱的用户,像左滑动视图可以展示删除按钮,祝您在嗨购商场中购物愉快"/><van-swipe-cellv-for="item of cartList":key="item.cartid"><van-row><van-col span="2"><div class="my-checkbox"><van-checkbox v-model="item.flag" @change="chooseOne(item.cartid, item.flag)"></van-checkbox></div></van-col><van-col span="22"><van-card:price="item.originprice":title="item.proname":thumb="item.img1"><template #num><van-stepper v-model="item.num" theme="round" button-size="22" @change="updateCartNum(item.num, item.cartid)"/></template></van-card></van-col></van-row>
​<template #right><van-button square text="删除" type="danger" class="delete-button" @click="deleteCart(item.cartid)"/></template></van-swipe-cell><van-submit-bar :price="totalPrice" button-text="提交订单" @submit="onSubmit"><van-checkbox v-model="checked" @click="chooseAll">全选</van-checkbox></van-submit-bar></div><van-divider>猜你喜欢</van-divider><ProList :proList="proList"></ProList></div></div>
</template>
<script>
import Vue from 'vue'
import { Divider, NavBar, Empty, Button, Card, Stepper, SwipeCell, NoticeBar, SubmitBar, Checkbox, Col, Row } from 'vant'
import { getCartList, remove, updateNum, selectAll, selectOne, getRecommendList } from '../../api/cart'
import ProList from '@/components/ProList.vue'
Vue.use(Divider)
Vue.use(NavBar)
Vue.use(Empty)
Vue.use(Button)
Vue.use(Card)
Vue.use(Stepper)
Vue.use(SwipeCell)
Vue.use(NoticeBar)
Vue.use(SubmitBar)
Vue.use(Checkbox)
Vue.use(Col)
Vue.use(Row)
export default {components: {ProList},data () {return {empty: true,cartList: [],checked: false, // 全选proList: []}},computed: {totalNum () {return this.cartList.reduce((sum, item) => {return item.flag ? sum + item.num : sum + 0}, 0)},totalPrice () {return this.cartList.reduce((sum, item) => {return item.flag ? sum + item.num * item.originprice : sum + 0}, 0) * 100}},methods: {onSubmit () {console.log('提交订单')},chooseOne (cartid, flag) {console.log(cartid, flag)selectOne({ cartid, flag }).then(() => this.getCartListData())},chooseAll () {selectAll({userid: localStorage.getItem('userid'),type: this.checked // 数据的双向绑定}).then(() => this.getCartListData())},deleteCart (cartid) {remove({ cartid }).then(() => this.getCartListData())},updateCartNum (num, cartid) {console.log(num, cartid)updateNum({num, cartid}).then(() => this.getCartListData())},getCartListData () {getCartList({userid: localStorage.getItem('userid')}).then(res => {console.log(res.data)if (res.data.code === '10020') {this.empty = truethis.cartList = [] // 临界值变化 - 否则删除完所有的商品,商品总数量有问题} else {this.empty = falsethis.cartList = res.data.data// 判断全选的状态this.checked = this.cartList.every(item => item.flag)}})}},mounted () {if (localStorage.getItem('loginState') === 'true') {// 前端校验为登录状体啊this.getCartListData()} else {this.$router.push('/login')}getRecommendList().then(res => {this.proList = res.data.data})}
}
</script>
​
<style lang="stylus">
.delete-buttonheight 100%
.my-checkboxheight 1.04rembackground-color #fffdisplay flexjustify-content centeralign-items center
</style>
​

VueDemo-12.加入购物车相关推荐

  1. 面试时如何回答购物车测试步骤?

    同学们在面试软件测试工程师的时候如果是一个电商的公司,可能会问到你购物车的测试步骤都有哪些,一个是关于购物车的测试,一个就是支付类的测试,这里小千就来告诉大家购物车测试步骤都有哪些,避免面试的时候不会 ...

  2. java购物车后台_java开发——购物车功能如何实现

    java web开发_购物车功能实现 之前没有接触过购物车的东东,也不知道购物车应该怎么做,所以在查询了很多资料,总结一下购物车的功能实现. 查询的资料,找到三种方法: 1.用cookie实现购物车: ...

  3. 发泄键盘?养生鼠标?这届程序员这么过双12!

    又是一年一度的"剁手节",在女生购物车里装满了化妆品.包包.衣服.鞋子等等东西时,有类人的购物车里的东西画风十分清奇,不落俗套.这类人穿着统一.爱好相似.有明显的群体特征,这就是程 ...

  4. 淘宝购物车(提交订单)测试用例

    功能测试: 1.测试订单输入的类型 2.测试金额数量:可创建等价类划分 3.测试库存数量变更 4.测试订单是否生成 5.测试提交订单按键是否正常响应 6.点击下单后是否会显示订单信息进行再次核对 7. ...

  5. 终极完美《简易商城购物车系统》揭秘--MVC设计模式

    <简易商城购物系统> 大家经常去网上够物,对网上所谓的购物车应该不会陌生吧,那么今天我们就用使用javaweb的MVC设计模式来实现一个网上购物系统的案例. 最终效果如下: 三层架构的简单 ...

  6. 注册ETM钱包瓜分糖果 更有机会独享8888元现金奖励

    不知不觉,双11已经过去大半个月了, 更可怕的是,双12要来了!! 各种商品活动让人眼花缭乱, 已经忍不住想要剁手了, 可看看余额,再看看花呗.信用卡... 土都吃不起了,怎么办?? 不要慌!! 为庆 ...

  7. 20150127--Session入库

    20150127--Session入库 和涛哥学习MVC三 目录 和涛哥学习MVC三.......................................................... ...

  8. 宇宙最全面试题目实录(二)

    1. 发红包方面写测试点 ==>看这篇发红包的测试点_多测师-侯sir的博客-CSDN博客 2.购物车测试点 ==>看这篇购物车测试点_多测师-侯sir的博客-CSDN博客 电梯测试点看这 ...

  9. 仿淘宝客户端电商平台android初级速成-张勇-专题视频课程

    仿淘宝客户端电商平台android初级速成-969人已学习 课程介绍         本教程从当下火热的商城项目入手,以讲师多年商城项目开发为核心,与北风网强强联手录制了<北风商城>And ...

  10. 史上最全软件测试工程师常见的面试题总结【杭州多测师】【面试题】【杭州多测师_王sir】...

    2021.3.8号早上 1.是否接触过自动化测试?若做过,使用什么工具,写过多少自动化测试用例: robotframework+selenium2library selenium 2.是否接触过数据库 ...

最新文章

  1. gym-101343K-Counting Time
  2. 写程序和做网店的压力都很大
  3. 电视剧潜伏的真正结局
  4. Vant-UI 表单组件(Field组件):验证表单元素表单提交 - 踩坑篇
  5. Java并发编程:synchronized
  6. onbeforeedit和onbeginedit数据不一致_深度解读,奔溃一致性、应用一致性的区别
  7. Unity中的Time
  8. 经历一番波折后的fedora以及wireshark
  9. 云计算示范项目_“云计算和大数据”重点专项2018年度项目申报指南
  10. [转]VMPlayer的Briged网络配置
  11. 7-46 新浪微博热门话题 (30分)
  12. TensorRT学习(1):通过pth生成wts文件
  13. 百度网盘html资源,百度网盘目录索引搭建教程:如何把百度网盘文件做成在线html目录...
  14. 云音乐vue开发日记
  15. Aurix TC397多核开发建议
  16. 详解电容触控芯片与指纹芯片的研发与生产流程
  17. 【python基础】python中的乌龟画图
  18. 读书笔记21:解释器模式
  19. NBA历史上最长的连胜和连败纪录!
  20. 程序员和产品经理之间的恩怨情仇 1

热门文章

  1. retrofit 响应时间_HTTP Retrofit 网络传输
  2. python替换ppt文本_Python操作PPT实现自动查找替换
  3. 计算机硬盘根目录是什么,硬盘根目录是什么意思?存放哪里?
  4. 小球弹跳及MATLAB实现
  5. 从麻将到“农药”,细数 AI 攻占的游戏领域
  6. 服务器删除的excel文件备份在哪里,microsoft excel备份文件在哪 - 卡饭网
  7. iOS仿苹果原生天气app总结
  8. 计算机重装后如何连接无线网络,电脑重装系统后无线网络连接不上怎么办
  9. 必要的系统组件未能正常运行,请修复Adobe Flash Player
  10. 【树形DP】保镖排队