uni-app购物车页面开发

1.加入购物车功能

detail.vue

<template>
	<view>
		<view>
			<image :src="proimg" mode=""></image>
			<view>产品名称: {{proname}} </view>
			<view>价格: {{price}} RMB</view>
			<view>产品详情: {{desc}} </view>
			<!-- 添加按钮 -->
			<button @click="addcart">加入购物车</button>
		</view>
	</view>
</template>

<script>
	import { request,toast } from '../../utils/index.js'
	export default {
		data() {
			return {
				proname: '',
				proid: '',
				proimg: '',
				desc: '',
				price: 0
			}
		},
		methods: {
			onLoad (options) {
				...
			},
			// 添加到购物车方法
			addcart () {
				try {
					// 首先获取本地存储的信息(前端校验登录)
				    const token = uni.getStorageSync('token');
					const userid = uni.getStorageSync('userid');
				    if (token && userid) { //如果本地有存储信息
				        request({ //请求加入购物车
				        	url: '/cart/add',
				        	method: 'POST',
				        	data: {
				        		token ,
				        		userid ,
				        		num: 1,
								proid: this.proid
				        	}
				        }).then(res => {
							if(res.data.code === '10119') { //如果是未登录的状态(后端校验登录)
								toast({title:'请先登录'}) //提示信息
								uni.navigateTo({ //对应地跳转到登陆页面
									url: '/pages/login/login'
								})
							} else {
								toast({title:'加入购物车成功!'})
							}
						})
				    } else {
						toast({title:'请先登录'})
					}
				} catch (e) {
				    console.log(e)
				}
				// 判断用户是否处于登录状态
				
			}
		}
	}
</script>

<style>

</style>

2.购物车页面显示商品列表

1.获取并渲染数据

首先要通过接口获取到购物车的数据(可以在onLoad或者mounted方法中获取数据):

<template>
	<view>
		<view v-if="flag"> 
			购物车空空如也,请先<navigator open-type="switchTab" url="/pages/home/home">选购</navigator>
		</view>
		<view v-else>
			<view class="cartlist">
				<view class="cartitem" v-for="(index,item) of cartlist" :key="index">
					<!-- 下面数据分别表示商品的名称,价格以及添加的商品的数量 -->
					{{ item.proname }}:{{ item.price }}RMB-----{{ item.num }}
					
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	import { request,toast } from '../../utils/index.js'
	export default {
		data() {
			return {
				flag: true,
				cartlist: []
			}
		},
		onLoad() {
			console.log("onLoad")
		},
		mounted() {
			console.log("mounted")
			try {
				// 要获取数据首先要用户id等信息(先判断在本地是否具有)
			    let token = uni.getStorageSync('token');
				let userid = uni.getStorageSync('userid');
				if(userid && token) { //如果本地存在数据
					request({
						url: '/cart',
						data: {
							userid,token
						}
					}).then(res => {
						if (res.data.code === '10019') { //表示当前用户是未登录的状态
							toast({title:'请先登录'}) //提示信息
							uni.navigateTo({ //对应地跳转到登陆页面
								url: '/pages/login/login'
							})
						} else if (res.data.code === '10012') { //表示购物车内空空如也
							toast({title:'请先添加商品'})
							this.flag = true
						} else {
							toast({title:'购物车列表数据获取出成功'}) //表示数据获取成功
							this.flag = false
							this.cartlist = res.data.data
						}
					})
				} else { //如果没有本地用户id数据那么需要先登录
					toast({title:'请先登录'}) //提示信息
					uni.navigateTo({ //对应地跳转到登陆页面
						url: '/pages/login/login'
					})
				}
			}catch(e) {
				console.log(e)
			}
		},
		methods: {
			
		}
	}
</script>

<style>

</style>

因为mounted()函数只会执行一次,所以当每次添加数据之后页面不会实时发生变化,需要重新刷新页面。如果需要数据实时变化,可以把mounted()函数改为onShow(),让每一次添加新的商品到购物车回到购物车页面时都能执行一次数据请求(onShow函数在每一次页面被显示时都会调用)。

2.计算商品总数量和总价格
<view> 总数: {{totalNum}}</view>
<view> 总价: {{totalPrice}}</view>
...
computed: {
    // 计算商品的总数
    totalNum() {
        let totalNum = 0;
        this.cartlist.map(item => {
        totalNum += item.num
    })
    	return totalNum
    },
    // 计算商品的总价
    totalPrice() {
        let totalPrice = 0;
        this.cartlist.map(item => {
        totalPrice += item.num * item.price
    })
   		return totalPrice
    }
},

3.购物车商品数量的操作

首先要在页面上渲染出两个"按钮",绑定自定义事件,并把商品作为参数传递过去,在自定义方法内实现商品数量的增减即可:

<view class="cartitem" v-for="(index,item) of cartlist" :key="index">
    <!-- 下面数据分别表示商品的名称,价格以及添加的商品的数量 -->
    {{ item.proname }}:{{ item.price }}RMB-----{{ item.num }}
    <text @click="reduce(item)">[-]</text>
    <text @click="add(item)">[+]</text>
</view>
...
methods: {
    reduce(item) {
    	item.num -= 1
    },
    add(item) {
    	item.num += 1
    }
}

但是,这样当页面一刷新就会"一夜回归解放前"。不管是什么操作,都必须要经过服务器才能实现接口数据的更新。

reduce(item) {
    // 首先判断当前个数,如果是1那么不执行操作;如果>1,那么就-1
    let num = item.num
    if (num > 1) {
    	num -= 1
    } else {
   		num = 1
    }
    let token = uni.getStorageSync('token');
    request({ //这里的request请求就是在服务器端进行数据的更新
        url: '/cart/updata',
        data: {
            token,
            cartid: item.cartid,
            num
    }
    }).then(res => {
        if (res.data.code === '10019') { // 当用户长时间未登录信息失效时需要重新登录
            toast({title:'请先登录'}) 
            uni.navigateTo({ 
                url: '/pages/login/login'
            })
    } else {
        toast({title:'修改数量成功'}) 
        item.num -= 1 // 修改视图显示的数据
    }
    })			
},

add()方法同上类似,只不过不需要对num判断是否大于1,直接进行num += 1即可。

4.删除商品

删除商品的逻辑函数和商品数量的增减差不多:

<text @click="del(item,index)">[删除]</text>
...
del(item,index) {
    let token = uni.getStorageSync('token');
    request({ //这里的request请求就是在服务器端进行数据的更新
        url: '/cart/delete',
        data: {
            token,
            cartid: item.cartid,
    }
    }).then(res => {
        if (res.data.code === '10019') { // 当用户长时间未登录信息失效时需要重新登录
            toast({title:'请先登录'}) 
            uni.navigateTo({ 
            	url: '/pages/login/login'
            })
        } else {
            toast({title:'删除商品成功'}) 
            this.cartlist.splice(index,1) // 删除视图上的商品
			// 当商品删除完之后就显示没有数据了
			this.cartlist.length === 0 ? this.flag = true : this.flag = false 
        }
    })
}

购物车页面涉及到的数据变化都是需要先从服务器端进行数据的更新然后再

5.商品的选中

首先在每个商品前面加上复选框按钮组件

<checkbox-group @change="selected(item)">
	<checkbox :checked="item.flag" />
</checkbox-group>

在一开始获取购物车数据的时候加上数据项flag用于复选框的使用:

toast({title:'购物车列表数据获取出成功'}) //表示数据获取成功
this.flag = false
// 赋值之前给数据添加数据项 item.flag 用于复选框的使用
res.data.data.map(item => {
	item.flag = true //默认商品都处于被选中状态
})
this.cartlist = res.data.data

这样的话获取到的购物车数据中的商品一开始都是处于选中状态。

接下去就是写复选框的change事件:

methods: {
    selected (item) {
        console.log("test",item)
        item.flag = !item.flag //改变复选框的选中状态
        console.log(this.cartlist)
    }
    ...
}

完善商品数量的计算以及总价的计算

totalNum() {
    let totalNum = 0;
    this.cartlist.map(item => {
    	item.flag ? totalNum += item.num : totalNum += 0 //只有当该商品被选中时才会对数量进行累加
    })
    return totalNum
    },
    // 计算商品的总价
    totalPrice() {
    let totalPrice = 0;
    this.cartlist.map(item => {
    	item.flag ? totalPrice += item.num * item.price : totalNum += 0 //只有当该商品被选中时才会对价格进行累加
    })
    return totalPrice
}

6.全选按钮

先在所有的商品之前增加一个全选框按钮

<checkbox-group @change="allselected">
	<checkbox :checked="allselected" />
</checkbox-group>

然后写全选全不选的逻辑:

allselected () {
    this.allselected = !this.allselected
    console.log(this.allselected)
    // 如果this.allselected的值为true,那么全部商品的flag都为true,否则都为false
    if (this.allselected) {
        this.cartlist.map(item => {
        	item.flag = true
        })
    } else {
        this.cartlist.map(item => {
        	item.flag = false
        })
    }
}

当然还需要实现两个功能:1.当处于全选状态的时候如果取消选择了某一件商品那么全选框也对应的会取消选择;2.当没有处于全选状态的时候,如果逐一把所有商品都选择了,那么对应的全选框也会被选择。

selected (item) {
    console.log("test",item)
    item.flag = !item.flag
    console.log(this.cartlist)
    // 如果单独某一项不被选中,那么全选框一定不被选中
    if(!item.flag) { //当前项是被选中的状态
    	this.allselected = false
    } else {
    // 检测其余项是否被选中
        const test = this.cartlist.every(item => {
        	return item.flag === true
        })
        if (test) {
        	this.allselected = true
        } else {
        	this.allselected = false
        }
    }
    //如果全部项都被选中,那么全选框一定被选中
}
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐