分析
添加购物车
- 商品添加到购物车
- 加入购物车前判断是否已登录(本文主要实现下面第2点)
- 未登录,将记录添加到Vuex的cart模块中
- 修改本地购物车后,成功登录后,合并本地购物车并清空本地购物车
- 已登录,请求更新数据库的购物车表
使用到的技术
- Vuex
- Vuex模块化,创建cart模块带命名空间,state存储购物车列表
- Vuex模块化在模块中获取其他模块的state,使用actions的context的rootState
- 使用异步actions,store.dispatch(‘cart/mergeLocalCart’)
- 使用async和await获取请求的数据 - Axios
- POST请求,带参数
- Promise对象 - nodejs
- MySQL数据库新增、查询、修改
- 使用async和await获取请求的数据
- 取出需要的数据使用 arr.map()
- 查找购物车内是否已存在某一商品使用 arr.findIndex()
- req获取POST的参数,req.body - 测试接口工具 Postwoman
- 谷歌的Http接口插件
实现
前端
- Vuex创建cart模块,主要存本地购物车列表 [ { 商品id、商品名、商品图片、商品价格、已选数量、是否选择、是否有效 } , { … } , … ]
/* Vuex的cart模块的state */
state: () => {
return {
//{pro_id, pro_name, pro_main_images, pro_price, count: 1//已选择件数, selected: true, isEffective: true, pro_stock}
list: []
}
},
- Vuex的getters、mutations主要处理购物车其他逻辑,比如有效商品列表、金额、件数,已选商品列表、金额、件数,是否全选,增删改查购物车列表等
- Vuex的actions添加合并本地购物车函数mergeLocalCart。
- 判断是否登录,查询user模块的用户id,在管理购物车表时也需要用户id来查询用户所有购物车记录。
- 从购物车的有效商品列表中取出需要的数据 arr.map()
- axios使用post请求(request时axios封装后的函数返回Promise对象),将用户id和本地购物车参数传过去
- 使用mutations的修改购物车函数,将购物车清空 [],ctx.commit
/* Vuex的cart模块的actions */
//合并本地购物车
async mergeLocalCart(ctx) {
const userId = ctx.rootState.user.user.u_id;
// console.log("Store-Cart-userid",userId)
// 判断是否登录
if (userId) {
// 调用合并API接口函数进行购物合并
const cartList = ctx.getters.validList.map(({ pro_id, pro_price, selected, count }) => {
return { pro_id, pro_price, selected, count }
})
const res = await mergeCart(userId, cartList)
// console.log("Api-Cart-合并购物车mergeLocalCart-res", res);
// 合并成功将本地购物车删除
ctx.commit('setCartList', [])
} else {
console.log("用户还未登录");
}
}
/* api的购物车请求*/
/**
* axios的POST请求:合并本地购物车
* @param {Array<object>} cartList - 本地购物车数组
* @param {String} item.pro_id - 商品pro_id
* @param {Integer} item.pro_price - 商品价格
* @param {Boolean} item.selected - 是否选中
* @param {Integer} item.count - 数量
*/
export const mergeCart = (userId, cartList) => {
//cartList 是 { pro_id, pro_price, selected, count }对象数组
return request('/cart/merge', 'post', {userId,cartList})
}
- 在登录后,使用actions的mergeLocalCart,store.dispatch(‘cart/mergeLocalCart’)
/*登陆页面login-form.vue的主要代码*/
//登陆成功后合并购物车操作
store.dispatch('cart/mergeLocalCart').then(()=>{
// 2. 提示
Message({ type: "success", text: "登录成功" });
// 3. 跳转
router.push(route.query.redirectUrl || "/");
})
后端接口(‘cart/merge’)
- Path:‘cart/merge’
- Method:POST
- 接收参数:(用户id)req.body.userId;(购物车列表)req.body.cartList;
//cartList:[{ pro_id: 1, pro_price: 22, count: 1, selected: true }];
- 返回信息:合并后的数据库信息
- 操作数据库dao:查询某一用户的购物车信息;修改购物车信息;新增购物车信息;
/**
* 查询某一用户的购物车信息
*/
static queryByUserid(cart_user_id) {
return new Promise((resolve, reject) => {
let sql = `SELECT * FROM pin_cart WHERE cart_user_id = ${cart_user_id};`;
this.query(sql).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
/**
* 修改购物车
*/
static updateById(cart_id,good) {
return new Promise((resolve, reject) => {
let sql = `UPDATE pinke.pin_cart SET cart_product_id = ${good.pro_id} , cart_old_price = ${good.pro_price} , cart_count = ${good.count} , cart_selected = ${good.selected} ,cart_is_effective = '1' WHERE cart_id = ${cart_id}; `;
this.query(sql).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
/**
* 新增购物车商品
*/
static add(user_id,good) {
return new Promise((resolve, reject) => {
let sql = `INSERT INTO pin_cart (cart_user_id, cart_product_id, cart_old_price, cart_count, cart_selected, cart_is_effective) VALUES (${user_id}, ${good.pro_id}, ${good.pro_price}, ${good.count}, ${good.selected}, '1');`;
this.query(sql).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
- 数据处理controller
- 获取客户端传来的数据:用户id和购物车列表
- 获取客户的所有购物车记录let result = await this.queryByUserid(u_id);
- 循环每条本地购物车记录,是否在result 中已存在result.findIndex
,如果已存在则更新await this.updateById(result[index].cart_id,good);
,不存在则新增await this.add(u_id, good);
- 重新查询购物车result = await this.queryByUserid(u_id);
- 返回更新后的购车车信息res.json({ list: result })
module.exports = class user_dao extends require('../dao/cart_dao') {
/* 合并购物车 */
static async mergeCart(req, res) {
//获取客户端本地购物车信息
let u_id = req.body.userId;
let cartList = req.body.cartList;//cartList:[{ pro_id: 1, pro_price: 22, count: 1, selected: true }]
// console.log("mergeCart__________________req.body", req.body);
//先获取用户的所有购物车信息
let result = await this.queryByUserid(u_id);
//循环本地购物车,如果购物车内不存在则新增,若存在则修改
cartList.forEach(async good => {
//本地的商品是否在result中存在
let index = result.findIndex((currVal) => {
return currVal.cart_product_id === good.pro_id
})
// console.log("mergeCart__________________找到的index",index);
if (index===-1){
//新增
await this.add(u_id, good);
// console.log("mergeCart__________________新增");
}else{
//修改
await this.updateById(result[index].cart_id,good);
// console.log("mergeCart__________________修改");
}
});
result = await this.queryByUserid(u_id);
res.json({ list: result })
}
}
- 创建接口( ‘cart/merge’ )
const cart = require('../controller/cart')
/* POST 合并本地购物车. */
router.post('/merge', function (req, res) {
cart.mergeCart(req, res);
});
结尾
这是笔者的想法实现,如果有更好的想法希望大家留言给出意见,感谢