在上一篇文章中,我只是大概的介绍了一下我的购物车页面和功能,具体的实现,将会在本篇文档中详细介绍。
(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
};
以上就是我购物车的功能,文章内容有什么错误的地方,望斧正,谢谢~