uni-app ——小程序购物车基本功能的实现过程

文章目录


一、示例图

二、实现步骤

1.实现思路

关于实现思路在初次使用JS实现购物车时就有所讲解,其实实现思路都大致相同,理解了实现思路就很简单了,不明白的小伙伴可以翻看一下以前的相关文章。

2.静态页面的搭建

<template>
	<view>
		<!--顶部标题部分 -->
		<view class="title">
			<search-slot>
				<view class="left" slot="left"> </view>
				<view class="center" slot="center">
					<text>购物车</text>
				</view>
				<view class="right" slot="right" @click="flag = !flag">
					<text>{
   
   { flag ? "编辑" : "取消" }}</text>
				</view>
			</search-slot>
		</view>

		<!-- 商品列表区域 -->
		<template>
			<view class="goods-Container">
				<view class="goods-list d-flex" v-for="(item, index) in list" :key="item.id">
					<!-- 选中按钮区域-->
					<label class="radio">
						<checkbox color="orange" :checked="item.checked" @click="selectItem(index)" />
					</label>
					<!-- 商品图片及描述区域 -->
					<view class="d-flex j-center a-center">
						<image :src="item.cover" mode=""></image>
						<view class="desc">
							<view class="goods-title">
								<text>{
   
   { item.title }}</text>
							</view>
							<view class="goods-kind">
								<text>小米系列</text>
							</view>
							<view class="goods-price">
								<text>¥{
   
   { item.pprice }}</text>
							</view>
						</view>
					</view>
					<!-- 步进器区域 -->
					<view class="number">
						<u-number-box buttonSize="50" v-model="value" @change="valChange"></u-number-box>
					</view>
				</view>
			</view>
		</template>

		<!-- 底部全选合计价格区域 -->
		<view class="footer d-flex">
			<!-- 全选按钮-->
			<view class="radio-wrapper">
				<label class="radio">
					<checkbox value="cb" @click="selectAll" color="orange" :checked="isChooseAll" />
				</label>
			</view>
			<!-- 合计价格区域 -->
			<view class="footer-outer">
				<template v-if="flag">
					<view class="footer-main d-flex">
						<view class="footer-left"> 合计 <text class="totalPrice">{
   
   {totalPrice}}</text>元</view>
						<view class="footer-right" @click="delItem"> 删除 </view>
					</view>
				</template>
				<template v-if="flag == false">
					<view class="footer-main d-flex">
						<view class="footer-left"> 移入收藏 </view>
						<view class="footer-right" @click="delItem"> 删除 </view>
					</view>
				</template>
			</view>
		</view>
	</view>
</template>

3.css样式


<style scoped>
	/* 顶部搜索栏区域样式设置 */
	.left {
		width: 44rpx;
		flex: 0 0 44px;
		align-items: center;
		text-align: center;
	}

	.center {
		flex: 1;
		height: 60rpx;
		line-height: 60rpx;
		text-align: center;
	}

	.right {
		width: 44rpx;
		flex: 0 0 44px;
		align-items: center;
		text-align: center;
		padding-right: 15rpx;
	}

	/* 商品列表区域样式设置 */
	.goods-Container {
		margin-top: 60rpx;
		padding: 0 30rpx;
		height: 800rpx;
	}

	.goods-list {
		height: 210rpx;
		line-height: 210rpx;
		margin-top: 40rpx;
	}

	.number {
		margin-top: 140rpx;
	}

	.desc {
		margin-left: 20rpx;
		width: 200rpx;
	}

	.goods-title {
		line-height: 60rpx;
	}

	.goods-kind {
		line-height: 60rpx;
	}

	.goods-price {
		line-height: 60rpx;
		color: orange;
		font-size: 37rpx;
	}

	image {
		width: 200rpx;
		height: 200rpx;
		border-radius: 15rpx;
		border: 1px solid rgb(239, 239, 239);
		padding: 10rpx;
	}

	/* 底部全选区域样式设置 */
	.footer {
		padding-left: 30rpx;
		height: 120rpx;
		line-height: 120rpx;
		margin-top: 230rpx;
	}

	.radio-wrapper {
		width: 15%;
	}

	.footer-outer {
		width: 85%;
	}

	.footer-left {
		width: 50%;
		text-align: center;
		background: orange;
		opacity: 0.7;
		font-size: 34rpx;
	}

	.footer-right {
		width: 50%;
		text-align: center;
		background: orange;
		font-size: 34rpx;
	}

	.totalPrice {
		margin: 0 10rpx;
		color: red;
		font-size: 36rpx;
	}
</style>

4.使用vuex操作相关数据

4.1 创建vuex实例,并使用模块化的方式

// 引入vue
import Vue from 'vue';
// 引入vuex
import Vuex from 'vuex';
// 引入子模块
import cart from './cart.js';

// 使用vuex插件
Vue.use(Vuex);


// 创建 store 实例
const store = new Vuex.Store({
	modules: {
		cart,
	}
})

// 暴露vuex
export default store;

4.2 store下的子模块——包括数据与相关操作方法

export default {
	//开启命名空间
	namespaced: true,

	state: {
		list: [{
				checked: false,
				id: 11,
				title: "商品标题111",
				cover: "/static/images/demo/list/1.jpg",
				// 选中商品属性
				attrs: [{
						title: "颜色",
						selected: 0,
						list: [{
								name: '火焰红',
							},
							{
								name: '炭黑',
							},
							{
								name: '冰川兰',
							}
						]
					},
					{
						title: "容量",
						selected: 0,
						list: [{
								name: '64GB',
							},
							{
								name: '128GB',
							},
						]
					},
					{
						title: "套餐",
						selected: 0,
						list: [{
								name: '标配',
							},
							{
								name: '套餐一',
							},
							{
								name: '套餐二',
							}
						]
					},
				],
				pprice: 336,
				num: 1,
				minnum: 1,
				maxnum: 10, // 该商品最大商品数,跟库存有关
			},
			{
				checked: false,
				id: 12,
				title: "商品222",
				cover: "/static/images/demo/list/1.jpg",
				// 选中商品属性
				attrs: [{
						title: "颜色",
						selected: 0,
						list: [{
								name: '火焰红',
							},
							{
								name: '炭黑',
							},
							{
								name: '冰川兰',
							}
						]
					},
					{
						title: "容量",
						selected: 0,
						list: [{
								name: '64GB',
							},
							{
								name: '128GB',
							},
						]
					},
					{
						title: "套餐",
						selected: 0,
						list: [{
								name: '标配',
							},
							{
								name: '套餐一',
							},
							{
								name: '套餐二',
							}
						]
					},
				],
				pprice: 200,
				num: 1,
				minnum: 1,
				maxnum: 10, // 该商品最大商品数,跟库存有关
			},
			{
				checked: false,
				id: 13,
				title: "商品标题333",
				cover: "/static/images/demo/list/1.jpg",
				// 选中商品属性
				attrs: [{
						title: "颜色",
						selected: 0,
						list: [{
								name: '火焰红',
							},
							{
								name: '炭黑',
							},
							{
								name: '冰川兰',
							}
						]
					},
					{
						title: "容量",
						selected: 0,
						list: [{
								name: '64GB',
							},
							{
								name: '128GB',
							},
						]
					},
					{
						title: "套餐",
						selected: 0,
						list: [{
								name: '标配',
							},
							{
								name: '套餐一',
							},
							{
								name: '套餐二',
							}
						]
					},
				],
				pprice: 100,
				num: 2,
				minnum: 1,
				maxnum: 10, // 该商品最大商品数,跟库存有关
			}
		],
		// 设置一个数组用来承载商品列表中选中的那一条记录的id
		selectId: [],
	},
	actions: {
		// 全选
		chooseAll(context) {
			context.commit('CHOOSEALL')
		},
		// 单选
		chooseItem(context, index) {
			context.commit('CHOOSEITEM', index);
		},
		// 删除
		delItem(context){
			context.commit('DELITEM');
		},
		// 增加商品数量
		changeNum(context,value){
			context.commit('CHANGENUM',value)
		}




	},
	mutations: {
		// 全选
		CHOOSEALL(state, value) {
			if (state.list) {
				state.list.forEach((item) => {
					if (item.checked) {
						item.checked = false;
					} else {
						item.checked = true;
					}
				})
			}
			
		},
		// 切换每一条数据中的单选状态
		CHOOSEITEM(state, index) {
			let id = state.list[index].id;
			let i = state.selectId.indexOf(id);
			if (state.list) {
				if (i != -1) {
					state.selectId.splice(index, 1);
					state.list[index].checked = false;	
				} else {
					state.selectId.push(id);
					state.list[index].checked = true;	
				}
			}
		},
		// 删除每一条
		DELITEM(state){
			if(state.list){
				state.list = [];
			}
		},
	},

	getters: {
		// 比较选中数组中的长度是否与原数据数组长度相等
		isChooseAll(state) {
			return state.list.length == state.selectId.length;
		},
		// 计算总价
		totalPrice(state){
			let total = 0;
			if(state.list){
				state.list.forEach((item)=>{
					if(item.checked){
						total += item.pprice * item.num;
					}
				})
				return total;
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/Bonsoir777/article/details/127853595