uniapp-实现购物车弹框

最近在写一个小程序,其中设计到了购买商品的业务

我们知道,像美团和饿了么,还有淘宝京东这些知名app 都是有购物车的功能

下面我讲一下我实现的思路

=>  使用Vuex

=>  在添加删除时触发对应方法 

=>  判断是加还是减,并把数据做逻辑处理储存 

=>  触发Vuex内的方法,去修改或储存item数据 

=>  渲染到购物车的列表从Vuex内去取 

封装组件

因为不止在一个地方使用到了购物车,所以我选择封装一个组件,可以进行复用 

<template>
	<view>
		<view class="my-cart-mask" v-if="myShow" @click="hide"></view>
		<view class="my-cart animated" v-if="myShow" :class="{slideInUp: wrapper,slideOutDown: !wrapper}">
			<view class="title-wrapper">
				<view class="title">购物车</view>
				<view class="iconfont close" @click="hide"></view>
			</view>
			<view class="list-wrapper" v-if="list.length">
				<view class="cart-list">
					<view v-for="(item, index) in list" :key="index" class="cart-item">
						<cartItem :info="item"></cartItem>
					</view>
				</view>
				<view class="price-wrapper">
					<view class="price-item">包装费<text>¥4</text></view>
					<view class="price-item">配送费<text>¥4</text></view>
					<view class="price-item">快递费<text>¥4</text></view>
				</view>
			</view>
			<view class="empty" v-else>您的购物车是空的</view>
		</view>
	</view>
</template>

<script>
import cartItem from '../../components/cart_item';
const app = getApp();
export default {
	props: {
		show: {
			type: Boolean,
			default: false
		},
		info: {
			type: Object,
			default() {
				return {};
			}
		},
		list: {
			type: Array,
			default() {
				return [];
			}
		}
	},
	data () {
		return {
			mask: false,
			wrapper: false,
			myShow: false,
		};
	},
	mounted() {
	},
	watch: {
		show(isShow) {
			if (isShow) {
				this.myShow = isShow;
				this.wrapper = true;
			} else {
				this.wrapper = false;
				setTimeout(() => {
					this.myShow = false;
				}, 400);
			}
		},
	},
	methods: {
		hide() {
			this.wrapper = false;
			setTimeout(() => {
				this.$emit('handleHide', {
					show: false
				});
			}, 400);
		},
	},
	components: {
		cartItem
	},
};
</script>

<style lang="scss" scoped>
.my-cart-mask {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	top: 0;
	width: 100%;
	height: 100%;
	z-index: 5;
	background: rgba(28,28,28,0.2);
}
.my-cart {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 110rpx;
	z-index: 6;
	background: #fff;
	max-height: 80vh;
	padding: 8rpx 30rpx 32rpx;
	padding-bottom: env(safe-area-inset-bottom);
	box-sizing: border-box;
	border-radius: 20rpx 20rpx 0rpx 0rpx;
	.title-wrapper {
		height: 44rpx;
		display: flex;
		align-items: center;
		position: relative;
		padding-top: 38rpx;
		.title {
			font-size: 32rpx;
			font-family: PingFang SC;
			font-weight: 500;
			color: #333333;
		}
		.close {
			position: absolute;
			right: 0rpx;
			top: 44rpx;
			&:before {
				font-size: 30rpx;
				color: #000;
				content: '\eaf2';
			}
		}
	}
	.list-wrapper {
		.cart-list {
			max-height: calc(80vh - 156rpx);
			overflow: scroll;
		}
		.price-wrapper {
			height: 40rpx;
			display: flex;
			align-items: center;
			font-size: 28rpx;
			font-family: PingFang SC;
			font-weight: 600;
			color: #666666;
			.price-item {
				margin-right: 58rpx;
				text {
					font-family: PingFangSC-Semibold;
					margin-left: 16rpx;
				}
			}
		}
	}
	.empty {
		padding: 20rpx;
		text-align: center;
		font-size: 28rpx;
		color: #333;
	}
}
</style>

在父组件内去使用

<myCart :show="showCart" :info="info" @handleHide="showCart = false" :list="menuList"></myCart>

showCart 是去控制显示隐藏的

所以在初始化的时候就在data 内去定义的是 showCart: false

当我们点击关闭的时候 转变为false 点击特定按钮(更多)的时候 就转换成true

传入的值 list

list 是一个数组对象 是我们获取的一个商品列表,意思就是我们点击了 + 的商品 都添加到了 list 内去了

所以在这里就是把list 做循环 然后又引入了一个组件 把每一个item都传入进去 这个组件是渲染单个商品的

<cartItem :info="item"></cartItem>

<template>
	<view class="container">
		<view class="logo">
			<image :src="info.img"></image>
		</view>
		<view class="goods-info">
			<view class="name">{{info.name}}</view>
			<view class="price">¥{{info.fixPrice}}</view>
		</view>
		<view class="operate">
			<addCart :info="info" @handleOperate="handleOperate"></addCart>
		</view>
	</view>
</template>

<script>
import addCart from './add_cart';
const app = getApp();
export default {
	props: {
		info: {
			type: Object,
			default() {
				return {};
			}
		}
	},
	data () {
		return {
		};
	},
	mounted() {
	},
	methods: {
		handleOperate (index,item) {
			if(index == -1) {
				this.$store.commit('reduceFoods', item)
			} else if (index == 1) {
				this.$store.commit('addFoods', item)
			}
		},
	},
	components: {
		addCart
	},
};
</script>

<style lang="scss" scoped>
.container {
	display: flex;
	align-items: center;
	padding-top: 30rpx;
	.logo {
		margin-right: 20rpx;
		image {
			width: 168rpx;
			height: 118rpx;
			border-radius: 20rpx;
		}
	}
	.goods-info {
		flex: 1;
		font-size: 28rpx;
		font-family: PingFang SC;
		font-weight: 600;
		line-height: 40rpx;
		color: #666666;
		.name {
			padding-bottom: 10rpx;
		}
	}
}
</style>

这里也是引入了 addCart 就是用于加减商品的一个组件  这个组件也是需要去封装

使用Vuex状态管理库

首先就是下载和引入 这里不做多的讲解

这里只做展示  我都存到了 store/index 内去了

首先就是在Vuex内的mutations 内去定义方法

// 加
addFoods(state, item){
  let index = state.foodList.findIndex(v => v.id == item.id);
  if (index == -1) {
    item.cartNum = 1;
    state.foodList.push(item);
  } else {
    state.foodList[index].cartNum++;
  };
},
// 减
reduceFoods(state, item){
  let index = state.foodList.findIndex(v => v.id == item.id);
  state.foodList[index].cartNum--;
},

这里的加 我是去通过id去判断list内有没有这个商品 有就++ 没有就push

当然 是用的findIndex 去查找 如果没找到就返回的是 -1

减法就不用处理这种情况 因为数量到1时可以隐藏 - 的按钮 不让用户去 - 当然也可以写类似的判断 但是会更麻烦一点

减的时候也是通过 findIndex 去判断index 也就是商品在list 的位置 从而去--

在加减组件内定义处理逻辑

在addCart 也就是加减模块的里面 给 + 和 - 都绑定事件

@click="handleOperate(-1,info)"

通过传第一个 参数 去判断是+ 还是 -

第二个参数就是传点击的这个商品的信息

由于存Vuex的代码是写在父组件内 所以需要用$emit 去调用方法(需要在父组件内的子组件上绑定)

// 子组件
handleOperate (index, item) {
  this.$emit('handleOperate', index, item);
}

// 父组件
<addCart :info="item" @handleOperate="handleOperate"></addCart>

handleOperate (index,item) {
  // console.log(index);
  if(index == -1) {
    this.$store.commit('reduceFoods', item)
  } else if (index == 1) {
    this.$store.commit('addFoods', item)
  }
  this.menuList = this.$store.state.foodList
},

在这里做了判断 如果是- 就调用Vuex内的做减的方法

如果是+就是调用加的方法,并且把对应的商品信息也是传递了过去

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本课程讲了Vue3+Vue2+Uni-app(uniapp)入门基础与实战,其中还重点讲解了ES6、TypeScript这些基础知识,实战由两大价值5000元的真实企业级项目组成,分别是仿京东电商网站和仿美团微信点餐小程序,同时两大项目代码全部赠送,还赠送前后端架构模板,工作中直接使用。VUE和uni-app是目前热门的前端框架,本课程教你如何快速学会VUE和uni-app并应用到实战,教你如何解决内存泄漏,常用UI库的使用,自己封装组件和插件,正式上线白屏问题,性能优化、解决iphoneX“刘海”兼容性问题、微信支付、微信授权登录,获取位置在地图上显示,获取用户所在的城市和街道信息,微信小程序发布审核等。对正在工作当中或打算学习VUE和uni-app高薪就业的你来说,那么这门课程便是你手中的葵花宝典。学习技巧:学习当中不要只看,一定要多敲代码,如果碰到某一个知识点不是很明白,不要钻牛角尖,千万不要因为一个点,放弃整个森林,接着往下学,硬着头皮开发项目。只要能亲自开发一个完整的项目,你会发现不明白的地方自然而然就明白了,项目做出来就真正的学会了。此vue和uni-app课程以面试和实战为基础进行讲解,每个知识点都会让你知道在实际项目开发中如何使用,学习后,可以开发大型项目,增强逻辑思维,至少让你拥有3年以上开发经验的实力!代码和ppt均可下载!免费提供《企业级完整实战项目接口文档》,绝对可用
以下是使用uniapp checkbox-group实现购物车全选的示例代码: 1. 在template中添加checkbox-group和checkbox组件 ``` <template> <view> <checkbox-group bindchange="selectAllChange"> <checkbox value="all" checked="{{allSelected}}">全选</checkbox> </checkbox-group> <view v-for="(item, index) in cartList"> <checkbox value="{{item.id}}" checked="{{item.selected}}" bindchange="selectChange">{{item.name}}</checkbox> </view> </view> </template> ``` 2. 在script中添加data属性和方法 ``` <script> export default { data() { return { cartList: [], // 购物车列表 allSelected: false // 是否全选 } }, onShow() { // 获取购物车列表 this.getCartList() }, methods: { // 获取购物车列表 getCartList() { // 省略获取购物车列表的代码 }, // 单个商品选中状态改变事件 selectChange(event) { const id = event.target.value const selected = event.detail.value.length > 0 // 更新购物车列表中对应商品的选中状态 this.cartList = this.cartList.map(item => { if (item.id === id) { item.selected = selected } return item }) // 判断是否全选 this.checkAllSelected() }, // 全选状态改变事件 selectAllChange(event) { const selected = event.detail.value.length > 0 // 更新购物车列表中所有商品的选中状态 this.cartList = this.cartList.map(item => { item.selected = selected return item }) // 更新全选状态 this.allSelected = selected }, // 检查是否全选 checkAllSelected() { const selectedList = this.cartList.filter(item => item.selected) this.allSelected = selectedList.length === this.cartList.length } } } </script> ``` 3. 在style中添加样式 ``` <style> .uni-checkbox { margin-right: 10px; } </style> ``` 4. 注意事项 - checkbox-group组件中的value值需要设置为all,并且checked值绑定allSelected变量; - checkbox组件中的value值需要设置为对应商品的id,并且checked值绑定商品的selected属性; - selectChange方法中需要更新对应商品的selected属性,并调用checkAllSelected方法检查是否全选; - selectAllChange方法中需要更新所有商品的selected属性,并更新allSelected变量; - checkAllSelected方法中需要筛选出已选中的商品,判断是否全选。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值