一、示例图
二、实现步骤
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;
}
}
}
}