目的:打造购物车的页面
"去结算"调整
调整src\views\shop\Cart.vue
......
去结算
调整src\views\shop\Cart.vue
......
去结算
src\store\index.js
import { createStore } from 'vuex'
export default createStore({
state: {
cartList: {
// 第一层级:商铺的id
// 第二层内容是商品内容以及购物数量
// shopId: {
// productID: {
// _id: '1',
// name: '番茄250g/份',
// imgUrl: '/i18n/9_16/img/tomato.png',
// sales: 10,
// price: 33.6,
// oldPrice: 39.6,
// count: 0
// }
// }
}
},
mutations: {
/**
* 加入或减少购物车数量
* @param {*} state
* @param {String} shopId 店铺id
* @param {String} productId 商品id
* @param {Object} productInfo 商品信息集
* @param {Number} num 加入购物车的数量
* @param {*} payload
*/
changeItemToCart(state, payload) {
const { shopId, productId, productInfo, num } = payload
// console.log(shopId, productId, productInfo)
const shopInfo = state.cartList[shopId] || {}
let product = shopInfo[productId]
if (!product) {
productInfo.count = 0
product = productInfo // 初始化
}
product.count += num
// && 短路运算符,前面的满足才会执行后面的逻辑,等价于if
num > 0 && (product.checked = true)
product.count <= 0 && (shopInfo[productId].count = 0)
// delete state.cartList[shopId]
shopInfo[productId] = product
// 赋值
state.cartList[shopId] = shopInfo
},
// 购物车勾选记录
changeItemChecked(state, payload) {
const { shopId, productId } = payload
const product = state.cartList[shopId][productId]
product.checked = !product.checked
},
// 清除购物车
changeCleanCartProducts(state, payload) {
const { shopId } = payload
state.cartList[shopId] = {}
},
// 购物车全选或者取消全选
setCartItemsChecked(state, payload) {
const { shopId } = payload
const products = state.cartList[shopId]
if (products) {
for (const i in products) {
const product = products[i]
product.checked = true
}
}
}
},
actions: {},
modules: {}
})
之前存入src\store\index.js
// 第一层级:商铺的id
// 第二层内容是商品内容以及购物数量
// shopId: {
// productID: {
// _id: '1',
// name: '番茄250g/份',
// imgUrl: '/i18n/9_16/img/tomato.png',
// sales: 10,
// price: 33.6,
// oldPrice: 39.6,
// count: 0
// }
// }
在订单层面,需要显示商品名字等商铺的信息,明显这个结构不够用。优化结构如下:
// shopId: {
// shopName: '沃什么码',
// productList: {
// productId: {
// _id: '1',
// name: '番茄250g/份',
// imgUrl: '/i18n/9_16/img/tomato.png',
// sales: 10,
// price: 33.6,
// oldPrice: 39.6,
// count: 0
// }
// }
// }
那么相应的更新代码也要调整:
src\store\index.js
import { createStore } from 'vuex'
export default createStore({
state: {
cartList: {
// shopId: {
// shopName: '沃什么码',
// productList: {
// productId: {
// _id: '1',
// name: '番茄250g/份',
// imgUrl: '/i18n/9_16/img/tomato.png',
// sales: 10,
// price: 33.6,
// oldPrice: 39.6,
// count: 0
// }
// }
// }
// ================== 之前版本的结构 ==================
// 第一层级:商铺的id
// 第二层内容是商品内容以及购物数量
// shopId: {
// productID: {
// _id: '1',
// name: '番茄250g/份',
// imgUrl: '/i18n/9_16/img/tomato.png',
// sales: 10,
// price: 33.6,
// oldPrice: 39.6,
// count: 0
// }
// }
}
},
mutations: {
/**
* 加入或减少购物车数量
* @param {*} state
* @param {String} shopId 店铺id
* @param {String} productId 商品id
* @param {Object} productInfo 商品信息集
* @param {Number} num 加入购物车的数量
* @param {*} payload
*/
changeItemToCart(state, payload) {
const { shopId, productId, productInfo, num } = payload
// console.log(shopId, productId, productInfo)
const shopInfo = state.cartList[shopId] || {
shopName: '',
productList: {}
}
let product = shopInfo?.productList[productId]
if (!product) {
productInfo.count = 0
product = productInfo // 初始化
}
product.count += num
// && 短路运算符,前面的满足才会执行后面的逻辑,等价于if
num > 0 && (product.checked = true)
product.count <= 0 && (shopInfo[productId].count = 0)
// delete state.cartList[shopId]
shopInfo.productList[productId] = product
// 赋值
state.cartList[shopId] = shopInfo
},
// 购物车勾选记录
changeItemChecked(state, payload) {
const { shopId, productId } = payload
const product = state.cartList[shopId].productList[productId]
product.checked = !product.checked
},
// 清除购物车
changeCleanCartProducts(state, payload) {
const { shopId } = payload
state.cartList[shopId].productList = {}
},
// 购物车全选或者取消全选
setCartItemsChecked(state, payload) {
const { shopId } = payload
const products = state.cartList[shopId].productList
if (products) {
for (const i in products) {
const product = products[i]
product.checked = true
}
}
},
/**
* 修改商店名称
* @param {Object} state vuex对象
* @param {Object} payload 传值
*/
changeShopName(state, payload) {
const { shopId, shopName } = payload
const shopInfo = state.cartList[shopId] || {
shopName: '',
productList: {}
}
shopInfo.shopName = shopName
state.cartList[shopId] = shopInfo
}
},
actions: {},
modules: {}
})
src\views\shop\Shop.vue
src\views\shop\Content.vue
{{ item.name }}
{{ item.name }}
月售{{ item.sales }}件
¥{{ item.price }}
¥{{ item.oldPrice }}
{
changeCartItem(shopId, item._id, item, -1, shopName)
}
"
>-
{{ cartList?.[shopId]?.productList.[item._id]?.count || 0 }}
{
changeCartItem(shopId, item._id, item, 1, shopName)
}
"
>+
src\views\shop\commnCartEffect.js
import { toRefs } from 'vue'
import { useStore } from 'vuex'
// 添加、减少到购物车功能
export const useCommonCartEffect = () => {
const store = useStore()
const { cartList } = toRefs(store.state)
/**
* 加入或减少购物车数量
* @param {String} shopId 店铺id
* @param {String} productId 商品id
* @param {Object} productInfo 商品信息集
* @param {Number} num 加入购物车的数量
*/
const changeCartItemInfo = (shopId, productId, productInfo, num) => {
console.log(
'changeCartItemInfo:',
'shopId:' + shopId,
'productId:' + productId,
'productInfo:' + JSON.stringify(productInfo),
'num:' + num
)
// 更新vuex中的值
store.commit('changeItemToCart', { shopId, productId, productInfo, num })
}
return { cartList, changeCartItemInfo }
}
src\views\shop\Cart.vue
全选
清空购物车
{{ item.name }}
¥{{ item.price }}
¥{{ item.oldPrice }}
{
0
changeCartItemInfo(shopId, item._id, item, -1)
}
"
>-
{{ cartList?.[shopId]?.productList.[item._id]?.count || 0 }}
{
changeCartItemInfo(shopId, item._id, item, 1)
}
"
>+
{{ total }}
总计:¥ {{ totalPrice }}
去结算
最终效果如下:
继续优化一下src\views\shop\Content.vue中的流程代码:
优化购物车为空时,全选和清空购物车也不显示,修改src\views\shop\Cart.vue
:
......
优化计算属性:
全选
清空购物车
{{ item.name }}
¥{{ item.price }}
¥{{ item.oldPrice }}
{
0
changeCartItemInfo(shopId, item._id, item, -1)
}
"
>-
{{ cartList?.[shopId]?.productList.[item._id]?.count || 0 }}
{
changeCartItemInfo(shopId, item._id, item, 1)
}
"
>+
{{ calculations.total }}
总计:¥ {{ calculations.totalPrice }}
去结算
这里还可以将参数封装一下
src\views\shop\Content.vue
......
{
changeCartItem(shopId, item._id, item, -1, shopName)
}
"
>-
{{ getProductCartCount(shopId, item._id) }}
{
changeCartItem(shopId, item._id, item, 1, shopName)
}
"
>+
......
将值存入localstorage
修改src\store\index.js
import { createStore } from 'vuex'
const setLocalStorage = state => {
const cartList = state.cartList
const cartListString = JSON.stringify(cartList)
localStorage.cartList = cartListString
}
export default createStore({
state: {
cartList: {
// shopId: {
// shopName: '沃什么码',
// productList: {
// productId: {
// _id: '1',
// name: '番茄250g/份',
// imgUrl: '/i18n/9_16/img/tomato.png',
// sales: 10,
// price: 33.6,
// oldPrice: 39.6,
// count: 0
// }
// }
// }
// ================== 之前版本的结构 ==================
// 第一层级:商铺的id
// 第二层内容是商品内容以及购物数量
// shopId: {
// productID: {
// _id: '1',
// name: '番茄250g/份',
// imgUrl: '/i18n/9_16/img/tomato.png',
// sales: 10,
// price: 33.6,
// oldPrice: 39.6,
// count: 0
// }
// }
}
},
mutations: {
/**
* 加入或减少购物车数量
* @param {*} state
* @param {String} shopId 店铺id
* @param {String} productId 商品id
* @param {Object} productInfo 商品信息集
* @param {Number} num 加入购物车的数量
* @param {*} payload
*/
changeItemToCart(state, payload) {
const { shopId, productId, productInfo, num } = payload
// console.log(shopId, productId, productInfo)
const shopInfo = state.cartList[shopId] || {
shopName: '',
productList: {}
}
let product = shopInfo?.productList[productId]
if (!product) {
productInfo.count = 0
product = productInfo // 初始化
}
product.count += num
// && 短路运算符,前面的满足才会执行后面的逻辑,等价于if
num > 0 && (product.checked = true)
product.count <= 0 && (shopInfo[productId].count = 0)
// delete state.cartList[shopId]
shopInfo.productList[productId] = product
// 赋值
state.cartList[shopId] = shopInfo
setLocalStorage(state)
},
// 购物车勾选记录
changeItemChecked(state, payload) {
const { shopId, productId } = payload
const product = state.cartList[shopId].productList[productId]
product.checked = !product.checked
setLocalStorage(state)
},
// 清除购物车
changeCleanCartProducts(state, payload) {
const { shopId } = payload
state.cartList[shopId].productList = {}
setLocalStorage(state)
},
// 购物车全选或者取消全选
setCartItemsChecked(state, payload) {
const { shopId } = payload
const products = state.cartList[shopId].productList
if (products) {
for (const i in products) {
const product = products[i]
product.checked = true
}
}
setLocalStorage(state)
},
/**
* 修改商店名称
* @param {Object} state vuex对象
* @param {Object} payload 传值
*/
changeShopName(state, payload) {
const { shopId, shopName } = payload
const shopInfo = state.cartList[shopId] || {
shopName: '',
productList: {}
}
shopInfo.shopName = shopName
state.cartList[shopId] = shopInfo
}
},
actions: {},
modules: {}
})
完善读取:
import { createStore } from 'vuex'
/**
* 存入localStorage
* @param {Object} state
*/
const setLocalCartList = state => {
const cartList = state.cartList
const cartListString = JSON.stringify(cartList)
localStorage.cartList = cartListString
}
/**
* 从localStorage读取
* @param {Object} state
*/
const getLocalCartList = () => {
return JSON.parse(localStorage.cartList) || {}
}
export default createStore({
state: {
cartList: getLocalCartList()
......
这样刷新也能看到数据回显。