通常,我们做移动端商城的时候,通常会有购物车模块,那购物车模块有两种实现方式,一是储存在后台通过接口获取到购物车信息,二是存在用户手机本地,第一种方法只要调用接口获取比较简单,这里介绍的是第二种方法,利用vuex将购物车数据存在本地的方法。

vue项目创建方法和vuex的写法之前博文都有介绍,这里就不再重复了;

vant安装:

# 通过 npm 安装
npm i vant -S # 通过 yarn 安装
yarn add vant

具体使用方法请去它的官网了解

地址:https://youzan.github.io/vant/#/zh-CN/

购物车页面编写和本地的价格计算:

1.我们把vant按需引入,我们用到了Icon, Checkbox, Stepper, SubmitBar, Toast这些组件;

2.为了方便复制即用,我在本地写了一些购物车死数据goods用于渲染;

3.虽说是把商品信息购物车存在本地,实际上我们只需要存商品id和商品数量num;

4.我们需要通过单选的change事件,全选事件,步进器增加减少进行价格换算;

为了方便复制粘贴直接看效果,直接上demo

demo.html

<template>
<div class="shopCart">
<div class="cartList">
<ul v-if="goods.length > 0">
<li v-for="item in goods" :key="item.id">
<van-checkbox
:value="item.id"
v-model="item.isChecked"
checked-color="#15C481"
@click="chooseChange(item.id, item)"
></van-checkbox>
<div class="shopdetail">
<div class="detailimg">
<img :src="item.thumb" />
</div>
<div class="detailtext">
<div class="shoptitle van-multi-ellipsis--l2">
{{ item.title }}
</div>
<div class="shoppricenum">
<p class="shopprice">
¥{{ item.price
}}{{ item.lvd > 0 ? "+" + item.lvd + "LVD" : "" }}
</p>
<div class="shopnum">
<van-stepper v-model="item.num" @change="onChange(item)" />
</div>
</div>
</div>
</div>
</li>
</ul>
<div class="nohaveshop" v-else>
<van-icon name="shopping-cart-o" />
<p class="p1">你的购物车空空如也~~</p>
<p class="p2">快去采购吧!</p>
</div>
</div>
<div class="cartfotter" v-if="goods.length > 0">
<van-submit-bar button-text="去结算" @submit="onSubmit">
<van-checkbox
v-model="allchecked"
checked-color="#15C481"
@click="checkAll"
>全选</van-checkbox
>
<div class="buyprice">
<p class="p1">合计</p>
<p class="p2">
¥{{ totalprice }}{{ totallvd > 0 ? "+" + totallvd + "LVD" : "" }}
</p>
</div>
</van-submit-bar>
</div>
</div>
</template> <script>
import { Icon, Checkbox, Stepper, SubmitBar, Toast } from "vant";
export default {
components: {
[Icon.name]: Icon,
[Checkbox.name]: Checkbox,
[Stepper.name]: Stepper,
[SubmitBar.name]: SubmitBar,
[Toast.name]: Toast
},
data() {
return {
goods: [
{
id: 1,
title: "Zoneid 2019 新款羊羔绒蓝白拼接立领夹克男 9.9成新",
price: 980,
lvd: 12,
num: 1,
thumb:
"https://img.yzcdn.cn/public_files/2017/10/24/2f9a36046449dafb8608e99990b3c205.jpeg"
},
{
id: 2,
title: "青春女装复古时尚保暖拼接翻领夹克",
price: 1200,
lvd: 0,
num: 2,
thumb:
"https://img.yzcdn.cn/public_files/2017/10/24/f6aabd6ac5521195e01e8e89ee9fc63f.jpeg"
},
{
id: 3,
title: "成熟男装新款西装立体拼接立领夹克和正装",
price: 1000,
lvd: 8,
num: 1,
thumb:
"https://img.yzcdn.cn/public_files/2017/10/24/320454216bbe9e25c7651e1fa51b31fd.jpeg"
}
],
allchecked: false,
selectedData: [],
// 总价
totalprice: 0,
totallvd: 0
};
},
created: function() {
this.count();
},
computed: {},
methods: {
// 单选的change事件
chooseChange(i, item) {
Toast(i);
if (this.selectedData.indexOf(i) > -1) {
console.log(i);
var arrs = this.selectedData.filter(function(item) {
return item != i;
});
this.selectedData = arrs;
item.isChecked = false;
// this.remove(this.selectedData, i);
this.count();
console.log(this.selectedData);
} else {
this.selectedData.push(i);
item.isChecked = true;
this.count();
}
if (this.selectedData.length < this.goods.length) {
this.allchecked = false;
} else {
this.allchecked = true;
}
this.count();
console.log(this.selectedData);
},
// 商品数量
onChange(item) {
Toast(item.num);
this.count();
console.log(this.goods);
},
// 计算价格
count: function() {
var totalPrice = 0; //临时总价
var totalLvd = 0; //临时lvd
this.goods.forEach(function(val) {
if (val.isChecked) {
totalPrice += val.num * val.price; //累计总价
totalLvd += val.num * val.lvd; //累计lvd
}
});
this.totalprice = totalPrice;
this.totallvd = totalLvd;
},
// 全选
checkAll() {
let list = this.goods;
if (this.allchecked === true) {
list.forEach(element => {
element.isChecked = false;
});
this.selectedData = [];
this.count();
console.log("111" + this.selectedData);
} else {
list.forEach(element => {
element.isChecked = true;
if (this.selectedData.indexOf(element.id) < 0) {
this.selectedData.push(element.id);
}
});
this.count();
console.log("222" + this.selectedData);
}
},
// 去结算
onSubmit() {
// 选择购买的商品
var cartgoods = [];
this.goods.forEach(function(item) {
if (item.isChecked) {
cartgoods.push({ id: item.id, num: item.num });
}
});
if (cartgoods.length === 0) {
Toast("请选择商品购买");
} else {
this.$router.push("shopBuy");
}
console.log(cartgoods);
}
}
};
</script> <style lang="scss" scoped>
.shopCart {
width: 100%;
min-height: 100vh;
display: flex;
flex-direction: column;
background-color: #f6f6f6;
.cartList {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
margin-top: 16px;
ul {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 100px;
li {
width: 100%;
height: 96px;
background-color: #fff;
display: flex;
flex-direction: row;
align-items: center;
margin-bottom: 12px;
.van-checkbox {
margin-left: 17px;
::v-deep .van-checkbox__icon {
height: 14px;
line-height: 14px;
.van-icon {
width: 14px;
height: 14px;
font-size: 12px;
border: 1px solid #a5a5a5;
}
}
}
.shopdetail {
display: flex;
flex-direction: row;
align-items: center;
margin-left: 13px;
.detailimg {
width: 64px;
height: 64px;
background: rgba(165, 165, 165, 1);
border-radius: 4px;
img {
width: 100%;
height: 100%;
border-radius: 4px;
}
}
.detailtext {
width: 230px;
height: 60px;
display: flex;
flex-direction: column;
margin-left: 8px;
position: relative;
.shoptitle {
width: 180px;
text-align: justify;
font-size: 12px;
color: #212121;
line-height: 17px;
}
.shoppricenum {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
position: absolute;
bottom: 0px;
.shopprice {
font-size: 12px;
color: #15c481;
font-weight:;
}
.shopnum {
display: flex;
::v-deep .van-stepper {
button {
width: 14px;
height: 14px;
border: 1px solid #333333;
border-radius: 50px;
background-color: #fff;
}
.van-stepper__minus::before {
width: 8px;
}
.van-stepper__plus::before {
width: 8px;
}
.van-stepper__plus::after {
height: 8px;
}
.van-stepper__input {
font-size: 12px;
color: #333333;
background-color: #fff;
padding: 0px 12px;
}
}
}
}
}
}
}
}
.nohaveshop {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 100px;
.van-icon {
font-size: 60px;
color: #666;
}
p {
font-size: 14px;
color: #999;
}
.p1 {
margin-top: 20px;
}
}
}
.cartfotter {
width: 100%;
height: 60px;
position: fixed;
bottom:;
left:;
.van-submit-bar__bar {
height: 60px;
font-size: 16px;
.van-checkbox {
margin-left: 17px;
::v-deep .van-checkbox__icon {
height: 14px;
line-height: 14px;
.van-icon {
width: 14px;
height: 14px;
font-size: 12px;
border: 1px solid #a5a5a5;
}
}
::v-deep .van-checkbox__label {
font-size: 16px;
color: #212121;
margin-left: 9px;
}
}
.buyprice {
flex:;
padding-right: 8px;
text-align: right;
display: flex;
flex-direction: column;
.p1 {
font-size: 10px;
color: #001410;
}
.p2 {
font-size: 12px;
color: #15c481;
margin-top: 4px;
}
}
.van-button--danger {
width: 130px;
height: 60px;
background: rgba(21, 196, 129, 1);
border: none;
font-size: 16px;
color: #ffffff;
}
}
}
}
</style>

上面代码没用到vuex,目的是方便复制在进去就能直接运行,上面代码同样适用于接口获取购物车的情况,进行本地价格计算,vuex我在下面分开介绍,按需添加进去;

store下的index.js

import Vue from "vue";
import Vuex from "vuex";
import app from "@/store/module/cart";
Vue.use(Vuex); export default new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {
cart
}
});

上方代码我们创建了一个cart,专门用于购物车模块;

cart.js

export default {
state: {
// 购物车
cartGoods: []
},
getters: {
cartGoodIds(state) {
return state.cartGoods.map(item => item.productId);
}
},
mutations: {
INIT_CART(state) {
if (localStorage && localStorage.getItem("cartGoods")) {
const goods = JSON.parse(localStorage.getItem("cartGoods"));
state.cartGoods = goods;
}
},
ADD_TO_CART(state, addGood) {
const findGood = state.cartGoods.find(
item => item.productId === addGood.productId
);
if (findGood) {
findGood.num = findGood.num + addGood.num;
} else {
state.cartGoods.push(addGood);
}
if (localStorage) {
localStorage.setItem("cartGoods", JSON.stringify(state.cartGoods));
}
},
INPUT_TO_CART(state, inpGood) {
const findGood = state.cartGoods.find(
item => item.productId === inpGood.productId
);
const largeGood = state.cartGoods.find(item => item.num > inpGood.num);
const equalGood = state.cartGoods.find(item => item.num == inpGood.num);
const smallGood = state.cartGoods.find(item => item.num < inpGood.num);
if (findGood && largeGood) {
findGood.num = findGood.num - (findGood.num - inpGood.num);
}
if (findGood && equalGood) {
findGood.num = inpGood.num;
}
if (findGood && smallGood) {
findGood.num = inpGood.num;
}
if (localStorage) {
localStorage.setItem("cartGoods", JSON.stringify(state.cartGoods));
}
}
}
};

上方我们定义了一些计算方法和事件方法,来在其他页面调用时改变购物车储存的信息;

其他页面:

// 导入
import { mapGetters, mapMutations } from "vuex";
// 计算
computed: {
...mapGetters(["cartGoodIds"])
},
// 方法
methods: {
...mapMutations(["ADD_TO_CART", "INPUT_TO_CART", "INIT_CART"]),
}
// 使用
// 增加
// 增加
plusadd(item) {
this.$store.commit("ADD_TO_CART", {
productId: item.id,
num: 1
});
},
// 减少
minuscut(item) {
this.$store.commit("ADD_TO_CART", {
productId: item.id,
num: -1
});
},
// 输入
blurinput(item) {
this.$store.commit("INPUT_TO_CART", {
productId: item.id,
num: parseInt(item.num)
});
},

就先粗略的介绍到这里,有什么问题提出来我及时改正,谢谢!

Vue+Vant+Vuex实现本地购物车功能的更多相关文章

  1. 利用Vue实现一个简单的购物车功能

    开始学习Vue的小白,dalao多多指正 想要实现下面这个界面,包含总价计算.数量增加和移除功能 话不多说代码如下 <!DOCTYPE html> <html> <hea ...

  2. 基于vue2.0打造移动商城页面实践 vue实现商城购物车功能 基于Vue、Vuex、Vue-router实现的购物商城(原生切换动画)效果

    基于vue2.0打造移动商城页面实践 地址:https://www.jianshu.com/p/2129bc4d40e9 vue实现商城购物车功能 地址:http://www.jb51.net/art ...

  3. vue实战记录(五)- vue实现购物车功能之商品总金额计算和单选全选删除功能

    vue实战,一步步实现vue购物车功能的过程记录,课程与素材来自慕课网,自己搭建了express本地服务器来请求数据 作者:狐狸家的鱼 本文链接:vue实战-实现购物车功能(五) GitHub:sue ...

  4. vue实战记录(六)- vue实现购物车功能之地址列表选配

    vue实战,一步步实现vue购物车功能的过程记录,课程与素材来自慕课网,自己搭建了express本地服务器来请求数据 作者:狐狸家的鱼 本文链接:vue实战-实现购物车功能(六) GitHub:sue ...

  5. vue实战记录(四)- vue实现购物车功能之过滤器的使用

    vue实战,一步步实现vue购物车功能的过程记录,课程与素材来自慕课网,自己搭建了express本地服务器来请求数据 作者:狐狸家的鱼 本文链接:vue实战-实现购物车功能(四) GitHub:sue ...

  6. vue实战记录(三)- vue实现购物车功能之渲染商品列表

    vue实战,一步步实现vue购物车功能的过程记录,课程与素材来自慕课网,自己搭建了express本地服务器来请求数据 作者:狐狸家的鱼 本文链接:vue实战-实现购物车功能(三) GitHub:sue ...

  7. vue实战记录(二)- vue实现购物车功能之创建vue实例

    vue实战,一步步实现vue购物车功能的过程记录,课程与素材来自慕课网,自己搭建了express本地服务器来请求数据 作者:狐狸家的鱼 本文链接:vue实战-实现购物车功能(二) GitHub:sue ...

  8. vue实战记录(一)- vue实现购物车功能之前提准备

    vue实战,一步步实现vue购物车功能的过程记录,课程与素材来自慕课网,自己搭建了express本地服务器来请求数据 作者:狐狸家的鱼 本文链接:vue实战-实现购物车功能(一) GitHub:sue ...

  9. 用Vue来实现购物车功能(二)

    这个小demo具有添加商品进购物车 .增加购物车内商品的数量.减少购物车内商品的数量.计算一类商品的总价.以及计算所有商品的总价 首先看目录结构 因为我们的Tab.vue  Car.vue 以及Car ...

随机推荐

  1. Datamation Index

    Datamation Index     Understand how to handle big data and improve organizational agility to support ...

  2. H3C 以太网集线器

  3. js用for循环实现乘法口诀表

    for循环可以打印一个乘法口诀表.需要使用for循环的嵌套 <script> for(var i = 0; i <= 9; i++){ // 外层循环控制行数,外层循环执行一次,内层 ...

  4. Vue 小实例 跑马灯效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. P1035 台阶问题二

    题目描述 有 \(N\) 级的台阶,你一开始在底部,每次可以向上迈最多 \(K\) 级台阶(最少 \(1\) 级),问到达第 \(N\) 级台阶有多少种不同方式. 输入格式 两个正整数 \(N, K( ...

  6. Spring Data -Specification用法和常用查询方法(in,join,equal等)

    Spring Data -Specification用法和常用查询方法(in,join,equal等) 前言 入门例子 Repository层常用写法 Specification 的用法 总结 前言 ...

  7. Java 5,6,7,8,9,10,11新特性吐血总结

    作者:拔剑少年 简书地址:https://www.jianshu.com/u/dad4d9675892 博客地址:https://it18monkey.github.io 转载请注明出处 java5 ...

  8. H3C创建本地用户

    [H3C]Local-user wang                 //创建本地用户--对应上面scheme的 [H3C-luser-wang]Password cipher 456      ...

  9. 【38.96%】【hdu 1540】Tunnel Warfare

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission ...

  10. Linux 内核 kobject 初始化

    本书已经展示了许多数据类型, 带有简单的在编译或者运行时初始化机制. 一个 kobject 的初始化有些复杂, 特别当使用它的所有函数时. 不管一个 kobject 如何使用, 但是, 必须进行几个步 ...