uni-app微信公众号(3)——购物车

在上一篇文章中,我只是大概的介绍了一下我的购物车页面和功能,具体的实现,将会在本篇文档中详细介绍。

(1)选中、全选 

 

购物车中的选中,调用vuex中写的代码,要改变选中,和全选的状态,还要动态改变合计的金额。

代码如下:

HTML代码

<!-- 单选按钮 -->
<u-checkbox-group>
	<u-checkbox @change="goodCheckedProduct(item.id)" v-model="item.checked" :key="item.id"
							:name="item.id">
	</u-checkbox>
</u-checkbox-group>

<!-- 全选,合计金额,选中数量 -->
<view class="submitBar">
	<view class="left">
		<u-checkbox shape="circle" v-model="checked">全选</u-checkbox>
	</view>
	<view class="right">
		<text class="total-price">合计:
			<text class="money">¥{{totalPrice}}</text>
		</text>
	    <u-button class="jsBtn" size="mini" @click="toSettlement" type="warning">去祭祀                                                                
              ({{allSelectProduct}})
	    </u-button>
	</view>
</view>

JS代码

computed: {
			...mapGetters(['cartProducts', 'totalPrice', 'allSelectProduct', 'isSelectAll']),
			checked: {
				get() {
					return this.isSelectAll;
				},
				set(value) {
					console.log(value);
					this.goodCheckedAllProduct(value)
				}
			}
		},
methods: {
	...mapActions(['add', 'del', 'open', 'reduce', 'input']),
	...mapMutations(['goodCheckedProduct', 'goodCheckedAllProduct']),
}

 其中需要注意的是,在computed(){}方法中,checked:{}函数,是为了v-model绑定的值是一个变量,是无法应用 filter 的,如果需要应用filter(过滤的),所以要是有get(),set(),方法来双向绑定实现。

(2)更改数量、删除

 

 数量的更改,使用uView中的<u-number-box>组件

代码如下:

<view class="footerBtn">
	<u-number-box :index="item.id" v-model="item.num" :positive-integer="true" :input-height="46" :input-width="100" :min="1" @blur="changeNum" @minus="changeNum" @plus="changeNum">
    </u-number-box>
</view>

 商品的删除,是使用<u-swipe-action>的滑动删除

代码如下

// 删除
deleteGoods(id) {
	this.$refs.uToast.show({
		title: '已移除此商品',
		type: 'warning',
	})
	this.del(id);
},

 上面就是对我代码的拆分来解析的,下面我贴出我的全部代码

<template>
	<view class="carClass">
		<!-- 商品卡片栏 -->
		<view class="goodsClass">
			<u-empty class="noData"  :show="cartGoodsList.length == 0" text="购物车为空" mode="car"></u-empty>
			<!-- @open="open(index)"  -->
			<u-swipe-action :show="item.show" :index="index" v-for="(item, index) in cartGoodsList" :key="item.id"
				@click="deleteGoods(item.id)" @open="open(index)" @close="open(index)" :options="options">
				<view class="chengboxs">
					<u-checkbox-group>
						<u-checkbox @change="goodCheckedProduct(item.id)" v-model="item.checked" :key="item.id"
							:name="item.id">
						</u-checkbox>
					</u-checkbox-group>
				</view>
				<view class="item u-border-bottom">
					<image mode="aspectFill" :src="item.icon" />
					<!-- 此层wrap在此为必写的,否则可能会出现标题定位错误 -->
					<view class="title-wrap">
						<text class="title u-line-2">{{ item.title }}</text>
					</view>
					<view class="footerClass">
						<text class="price">¥{{ item.price }}</text>
						<text class="mPrice">¥{{ item.mPrice }}</text>
						<view class="footerBtn">
							<u-number-box :index="item.id" v-model="item.num" :positive-integer="true" :input-height="46" :input-width="100" :min="1" @blur="changeNum" @minus="changeNum" @plus="changeNum"></u-number-box>
						</view>
					</view>
				</view>
			</u-swipe-action>
		</view>
		<!--  -->
		<view class="submitBar">
			<view class="left">
				<u-checkbox shape="circle" v-model="checked">全选</u-checkbox>
			</view>
			<view class="right">
				<text class="total-price">合计:
					<text class="money">¥{{totalPrice}}</text>
				</text>
				<u-button class="jsBtn" size="mini" @click="toSettlement" type="warning">去祭祀({{allSelectProduct}})
				</u-button>
			</view>
		</view>
		<u-toast ref="uToast" />
	</view>
</template>

<script>
	import {
		mapState,
		mapGetters,
		mapActions,
		mapMutations
	} from 'vuex';
	export default {
		data() {
			return {
				checkBox: [], //选中的商品
				goodsList: [],
				noReduce: false,
				btnWidth: 180,
				show: false,
				number2: 3,
				options: [{
					text: '删除',
					style: {
						backgroundColor: '#dd524d'
					}
				}]
			};
		},
		onLoad() {

		},
		computed: {
			...mapState({
				cartGoodsList: state => state.cart.addCartList
			}),
			...mapGetters(['cartProducts', 'totalPrice', 'allSelectProduct', 'isSelectAll']),
			checked: {
				get() {
					return this.isSelectAll;
				},
				set(value) {
					console.log(value);
					this.goodCheckedAllProduct(value)
				}
			}
		},
		methods: {
			...mapActions(['add', 'del', 'open', 'reduce', 'input']),
			// 删除,仅打开一个,增加,减少
			...mapMutations(['goodCheckedProduct', 'goodCheckedAllProduct', 'getLocalstoreData']),
			// 删除
			deleteGoods(id) {
				this.$refs.uToast.show({
					title: '已移除此商品',
					type: 'warning',
				})
				this.del(id);
			},
			// 输入数量
			changeNum(data) {
				console.log(data);
				let id = data.index;
				let num = data.value;
				this.input({
					id,
					num
				});
			},
			//结算
			toSettlement() {
				// this.$u.toast(`立即祭祀(暂未实现,请期待)`);
				//去代祭祀页面
				this.$u.route({
					type: 'to',
					params: {},
					url: 'pages/view/personalFunction/personalSacrificialService/personalSSComponent/personal_replaceSac',
					animationType: 'slide-in-bottom'
				});
				
			},

		},
		mounted() {
			this.getLocalstoreData();
			// console.log(this.cartGoodsList);
		}
	}
</script>
<style>
	/* #ifndef H5 */
	page {
		width: 100%;
		height: 100%;
		background-color: #f2f2f2;
	}

	/* #endif */
</style>
<style lang="scss">
	.carClass{
		width: 100%;
		height: 100%;
	}
	.goodsClass{
		width: 100%;
		height: 100%;
		margin-bottom: 120rpx ;
	}
	.noData{
		padding-top: 50%;
		text-align: center;
	}
	.item {
		display: flex;
		padding: 20rpx 20rpx 20rpx 10rpx;
	}

	image {
		width: 120rpx;
		flex: 0 0 120rpx;
		height: 120rpx;
		margin-right: 30rpx;
		border-radius: 12rpx;
	}

	.title {
		text-align: left;
		font-size: 28rpx;
		color: $u-content-color;
		margin-top: 20rpx;
	}

	.chengboxs {
		width: 60rpx;
		padding: 66rpx 0 0 29rpx;
		height: 120rpx;
		float: left;
	}

	.footerClass {
		position: absolute;
		width: 93.5%;
		display: flex;
		top: 100rpx;
		left: 155rpx;
		height: 56rpx;

		.price {
			font-size: 26rpx;
			color: #ff1030;
			width: 80rpx;
			height: 56rpx;
			line-height: 56rpx;
			padding-right: 10rpx;
		}

		.mPrice {
			font-size: 24rpx;
			color: #a2a2a2;
			width: 80rpx;
			height: 56rpx;
			line-height: 56rpx;
			text-decoration: line-through;
		}

		.footerBtn {
			// padding-left:170rpx;
			padding-left: 126rpx;
			display: flex;

			.btn {
				width: 50rpx;
				height: 50rpx;
			}

			.inputClass {
				width: 50rpx;
				height: 50rpx;
				padding: 0rpx !important;
			}
		}

	}

	.submitBar {
		display: flex;
		position: fixed;
		border: solid 2rpx #f2f2f2;
		background-color: #ffffff;
		padding: 16rpx;
		bottom: 10rpx;
		border-radius: 16rpx;
		width: 100%;

		.left {
			width: 23%;
			padding-left: 20rpx;
		}

		.right {
			width: 75%;
			padding-top: 6rpx;

			.total-price {
				.money {
					font-weight: 600;
				}
			}

			.jsBtn {
				float: right;
			}
		}
	}
</style>

 (3)vuex中购物车相关代码

import jsGoodsData from '@/static/data/jsGoods.js';
import Vue from 'vue';
//初始化数据
const state = {
	shop_list: jsGoodsData.map((list, i) => {
		return list.foods;
	}).reduce((a, b) => {
		return a.concat(b);
	}),
	addCartList: [],

};
// getter 抛出去的数据
const getters = {
	// 计算选中合计 getters中可以调用getters
	totalPrice: (state, getters) => {
		return state.addCartList.reduce((total, n) => {
			// console.log(n);
			if (n.checked) {
				return total += n.price * n.num;
			}
			return total;
		}, 0);
	},
	//计算选中商品数量(只计算选中)
	allSelectProduct: (state, getters) => {
		return state.addCartList.reduce((total, n) => {
			if (n.checked) {
				return total + n.num;
			}
			return total;
		}, 0);
	},
	// 计算选中商品数量(全部)
	allCartGoods: (state, getters) => {
		return state.addCartList.reduce((total, n) => {
			return total + n.num;
		}, 0);
	},
	// 判断是否全选
	isSelectAll: (state) => {
		return state.addCartList.every(n => {
			return n.checked;
		});
	},
	// 获取选中的数据
	getCheckedGoods: (state) => {
		return state.addCartList.filter(list => {
			if (list.checked) return list
		})
	}
};
// action 异步的操作
const actions = {
	add({
		commit
	}, product) {
		commit('addToCart', {
			product: product
		});
	},
	del({
		commit
	}, product) {
		commit('delProduct', {
			id: product
		});
	},
	open({
		commit
	}, product) {
		commit('openProduct', {
			index: product
		});
	},
	reduce({
		commit
	}, product) {
		commit('reduceGoodProduct', {
			id: product
		});
	},
	input({
		commit
	}, product) {
		commit('inputProduct', {
			id: product.id,
			num: product.num,
		});
	},
};
//mutation
const mutations = {
	// 添加到购物车操作
	addToCart(state, {
		product
	}) { //解析id
		console.log(product);
		let record = state.addCartList.find(n => n.id == product.id);
		if (!record) {
			state.addCartList.push({
				...product,
				num: 1
			});
		} else {
			record.num++;
		}
		// console.info(record, state.addCartList);
		localStorage.setItem('cartList', JSON.stringify(state.addCartList));
	},
	// 获取缓存
	getLocalstoreData(state) {
		if (localStorage.getItem('cartList')) {
			state.addCartList = JSON.parse(localStorage.getItem('cartList')).map(item => Object.assign({}, item));

		}
	},
	// 删除购物车中的指定商品
	delProduct(state, {
		id
	}) {
		state.addCartList.forEach((n, i) => {
			if (n.id == id) {
				state.addCartList.splice(i, 1);
			}
		});
		localStorage.setItem('cartList', JSON.stringify(state.addCartList));
	},
	// 仅打开一个滑动
	openProduct(state, {
		index
	}) {
		console.log(index);
		state.addCartList[index].show = !state.addCartList[index].show;
		console.log(state.addCartList);
		state.addCartList.map((val, idx) => {
			if (index != idx) {
				state.addCartList[idx].show = false;
			}
		});
		localStorage.setItem('cartList', JSON.stringify(state.addCartList));
	},
	// 减少商品数据
	reduceGoodProduct(state, {
		id
	}) {
		state.addCartList.forEach((n, i) => {
			if (n.id == id) {
				n.num <= 1 ? 1 : n.num--;

			}
		});
		localStorage.setItem('cartList', JSON.stringify(state.addCartList));
	},
	// 输入框输入
	inputProduct(state, {
		id,
		num
	}) {
	
		let record = state.addCartList.find(n => n.id == id);
		if (record) {
			record.num = num;
			console.log('更新后的值' + record.num);
		}
		localStorage.setItem('cartList', JSON.stringify(state.addCartList));
	},
	// 改变商品的选中状态
	goodCheckedProduct(state, id) {
		// console.log(state.addCartList);
		const cartItem = state.addCartList.find(item => item.id == id);
		cartItem.checked = !cartItem.checked;
		localStorage.setItem('cartList', JSON.stringify(state.addCartList));
		console.log(state.addCartList);
	},
	// 改变商品的全选状态
	goodCheckedAllProduct(state, status) {
		state.addCartList.forEach(item => {
			item.checked = status;
		});
		localStorage.setItem('cartList', JSON.stringify(state.addCartList));
		console.log(state.addCartList);
	}
};
export default {
	state,
	mutations,
	actions,
	getters
};

 以上就是我购物车的功能,文章内容有什么错误的地方,望斧正,谢谢~

 

 

 

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值