在models中建一个用户模型user,用户模型需要关联
引入mongoose
var mongoose = require('mongoose');
拿到mongoose以后,需要创建Schema模型,模型的字段必须与数据库对应起来。
var userSchema = mongoose.Schema({
"userId":String, // 用户Id
"userName":String, // 用户名
"userPwd":String, // 用户密码
"orderList":Array, // 订单列表
"cartList":[ // 购物车列表
{
"productId": String, // 商品Id
"productName": String, // 商品名称
"salePrice":String, // 商品价格
"productImage":String, // 图片地址
"checked":String, // 是否选中
"productNum":String // 商品数量
}
],
"addressList":Array // 用户地址列表
});
通过module.exports进行输出,这样才能加载到 三个参数分别是 模型名,userSchema名,管理数据库集合名
module.exports = mongoose.model("User",userSchema,"users");
在商品模型models/goods.js中添加商品数量prodcutNum和是否选择属性checked
var produtSchema = new Schema({
"productId":String,
"productName":String,
"salePrice":Number,
"prodcutNum": Number,
"checked":String,
"prodcutImage": String
});
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
购物车业务逻辑
第一步:拿到用户信息,判断用户是否存在
第二步:如果用户信息中存在此商品,则添加商品数量
第三步:如果用户信息中不存在此商品,则添加此商品,并设置为选择状态
node后端代码
models/user.js 用户模型
var mongoose = require('mongoose')
var userSchema = mongoose.Schema({
"userId":String, // 用户Id
"userName":String, // 用户名
"userPwd":String, // 用户密码
"orderList":Array, // 订单列表
"cartList":[ // 购物车列表
{
"productId": String, // 商品Id
"productName": String, // 商品名称
"salePrice":String, // 商品价格
"productImage":String, // 图片地址
"checked":String, // 是否选中
"productNum":String // 商品数量
}
],
"addressList":Array // 用户地址列表
});
// 通过module.exports进行输出,这样才能加载到 三个参数分别是 模型名,userSchema名,管理数据库集合名
module.exports = mongoose.model("User",userSchema,"users");
node查询商品列表及添加购物车逻辑
routes/goods.js
var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Goods = require('../models/goods');
// 连接MongoDB数据库
mongoose.connect('mongodb://47.100.191.231:27017/dumall');
// 通过mongoose.connect.on的形式去监听数据库有没有连接成功
mongoose.connection.on("connected",function () {
console.log("MongoDB connected success.")
})
// 连接失败
mongoose.connection.on("error",function () {
console.log("MongoDB connected fail.")
})
// 连接断开
mongoose.connection.on("disconnected",function () {
console.log("MongoDB connected disconnected.")
})
// next是往后继续执行的对象
// 查询商品列表数据
router.get("/", function (req,res,next) {
let page = parseInt(req.param("page")); // 获取分页参数 第几页
let pageSize = parseInt(req.param("pageSize")); // 获取一页多少条数据 必须要是数字
let priceLevel = req.param("priceLevel"); // 接收筛选价格
let sort = req.param("sort"); // 获取排序参数
let skip = (page-1)*pageSize; // 分页计算公式
var priceGt = '',priceLte = ''; // 筛选价格的区间
let = params = {};
// 当priceLevel不等于all是执行,默认是all
if(priceLevel!='all'){
switch (priceLevel){
case '0':
priceGt = 0; priceLte=100;
break;
case '1':
priceGt = 100; priceLte=500;
break;
case '2':
priceGt = 500; priceLte=1000;
break;
case '3':
priceGt = 1000; priceLte=5000;
break;
}
params = {
salePrice:{
$gt:priceGt, // 筛选价格大于priceGt
$lte:priceLte // 筛选价格小于priceLte
}
}
}
// 通过skip param 和limit来实现分页, skip表示跳过几条数据 limit表示一页多少条数据
let goodsModel = Goods.find(params).skip(skip).limit(pageSize);
// 声明对哪个字段进行排序 ,这里如salePrice金额 sort 1 为升序,-1 为降序
goodsModel.sort({'salePrice':sort});
// 第一个是参数,目前没有入参
// 返回的是两个参数,第一个是报错err,第二个是文档
// 因为这里不是普通的查询,经过到这里已经执行了很多步骤了 下面通过exec来执行我们的方法
// exec这里不需要传入参数了,因为前面已经find 拿到结果了
goodsModel.exec(function (err,doc) {
if(err) {
res.json({
status:'1',
msg:err.message
});
} else {
// 如果没有报错就把结果输出
res.json({
status:'0',
msg:'',
result:{
count: doc.length,
list: doc
}
});
}
});
});
// 加入购物车
router.post("/addCart", function (req,res,next) {
// post获取前端参数需要使用req.body.属性名
var userId = '100000077',productId = req.body.productId;
var User = require('../models/user'); // 获取用户模型
// 查询当前用户
User.findOne({userId:userId}, function (err,userDoc) {
if(err) {
res.json({
status:"1",
msg:err.message
})
}else{
console.log("userDoc:"+userDoc);
if(userDoc) {
let goodsItem = '';
// 遍历购物车列表查询有没有此产品
userDoc.cartList.forEach(function (item) {
if(item.productId == productId){ // 如果购物车列表已经有了该商品,只将此商品数量加1
goodsItem = item;
item.productNum ++;
}
});
if(goodsItem){ // 如果此商品购物车里面已经有了,那么就更新一下productNum
userDoc.save(function (err2,doc2) {
if(err2) {
res.json({
status:"1",
msg:err2.message
})
}else{
res.json({
status:'0',
msg:'',
result:'suc'
})
}
});
} else { // 如果此商品购物车列表没有,那么则将此商品添加至购物车列表
Goods.findOne({productId:productId},function (err1,doc) {
if(err1) {
res.json({
status:"1",
msg:err1.message
})
}else{
if(doc) {
doc.productNum = 1;
doc.checked = 1;
userDoc.cartList.push(doc); // 将数据添加
userDoc.save(function (err2,doc2) {
if(err2) {
res.json({
status:"1",
msg:err2.message
})
}else{
res.json({
status:'0',
msg:'',
result:'suc'
})
}
});
}
}
});
}
}
}
})
});
// 通过module.exports进行输出,这样才能加载到
module.exports = router;
vue前端GoodList.vue 商品列表及添加购物车逻辑
<template>
<div>
<nav-header></nav-header>
<nav-bread>
<span>Goods</span>
</nav-bread>
<div class="accessory-result-page accessory-page">
<div class="container">
<div class="filter-nav">
<span class="sortby">Sort by:</span>
<a href="javascript:void(0)" class="default cur">Default</a>
<a @click="showFilterPop" href="javascript:void(0)" class="price">
Price
<svg class="icon icon-arrow-short"><use xlink:href="#icon-arrow-short"></use></svg>
</a>
<a href="javascript:void(0)" class="filterby stopPop" @click="showFilterPop">Filter by</a>
</div>
<div class="accessory-result">
<!-- filter -->
<div class="filter stopPop" id="filter">
<dl class="filter-price">
<dt>Price:</dt>
<dd><a href="javascript:void(0)" v-bind:class="{'cur':priceChecked=='all'}" @click="priceChecked='all'">All</a></dd>
<dd v-for="(price,index) in priceFilter" :key="index">
<a href="javascript:void(0)" @click="setPriceFilter(index)" v-bind:class="{'cur':priceChecked==index}">{{ price.startPrice }}-{{ price.endPrice }}</a>
</dd>
</dl>
</div>
<!-- search result accessories list -->
<div class="accessory-list-wrap">
<div class="accessory-list col-4">
<ul>
<li v-for="(item,index) in goodsList" :key="index">
<div class="pic">
<a href="#"><img v-lazy="'/static/'+item.productImage" alt=""></a>
</div>
<div class="main">
<div class="name">{{item.productName}}</div>
<div class="price">{{item.salePrice}}</div>
<div class="btn-area">
<a href="javascript:;" class="btn btn--m" @click="addCart(item.productId)">加入购物车</a>
</div>
</div>
</li>
</ul>
<div class="load-more" v-infinite-scroll="loadMore" infinite-scroll-disabled="busy" infinite-scroll-distance="30">
<img src="./../assets/loading-spinning-bubbles.svg" alt="" v-show="loading">
</div>
</div>
</div>
</div>
</div>
</div>
<!-- <div class="md-overlay" v-show="overLayFlag" @click="closePop"></div> -->
<nav-footer></nav-footer>
</div>
</template>
<script>
import './../assets/css/base.css'
import './../assets/css/product.css'
import './../assets/css/checkout.css'
import './../assets/css/login.css'
import NavHeader from '@/components/NavHeader.vue'
import NavFooter from '@/components/NavFooter.vue'
import NavBread from '@/components/NavBread.vue'
import axios from 'axios'
export default {
data () {
return {
goodsList: [],
sortFlag: true, // 排序字段
page:1, // 默认页
pageSize: 8, // 默认一页显示8条数据
busy:true,
loading:true,
// priceLevel:this.priceChecked, // 筛选选择价格
priceFilter:[
{
startPrice:'0.00',
endPrice:'100.00'
},
{
startPrice:'100.00',
endPrice:'500.00'
},
{
startPrice:'500.00',
endPrice:'1000.00'
},
{
startPrice:'1000.00',
endPrice:'5000.00'
}
],
priceChecked:'all'
// filterBy:false,
// overLayFlag:false
}
},
components: {
NavHeader,
NavFooter,
NavBread
},
mounted () {
this.getGoodList();
},
methods: {
getGoodList (flag) {
var param = { // 分页及排序参数
page:this.page,
pageSize: this.pageSize,
sort: this.sortFlag?1:-1, // 升序是1 降序是-1
priceLevel: this.priceChecked
}
this.loading = true;
axios.get("/goods", {params:param}).then((result)=>{
let res = result.data;
this.loading = false;
if(res.status=="0"){
if(flag){ // 如果是分页需要累计
// 将数组进行串联起来 concat表示将数组连接起来
this.goodsList = this.goodsList.concat(res.result.list);
if(res.result.count == 0){
this.busy = true;
} else {
this.busy = false;
}
} else { // 普通的请求
this.goodsList = res.result.list;
this.busy = false;
}
} else {
this.goodsList = [];
}
});
},
showFilterPop() { // 排序
// this.filterBy = true;
// this.overLayFlag = true;
this.sortFlag = ! this.sortFlag; // 点击后升序降序切换
this.page = 1; // 点击升降序后默认从第一页显示
this.getGoodList(); // 重新加载一次
},
loadMore () {
this.busy = true; // 在请求成功之前禁止再滚动加载
// 鼠标滚动实在太快了,滚动一秒钟可能有上千个请求,这样对服务器压力太大 因此必须要通过setTimeout来控制
// 只有第一个请求结束以后才能请求第二个
setTimeout(() => {
this.page++; // 滚动之后要给page++
this.getGoodList(true);
}, 500);
},
setPriceFilter(index) { // 价格过滤
this.priceChecked = index;
this.page = 1; // 价格过滤后分页从第一页重新开始
this.getGoodList();
// this.closePop();
},
addCart(productId) { // 添加购物车
axios.post("/goods/addCart",{
productId:productId
}).then((res)=>{
if(res.status==200){
alert("加入成功");
}else{
alert("msg:"+res.msg);
}
});
}
}
}
</script>
转载自原文链接, 如需删除请联系管理员。
原文链接:加入购物车功能实现,转载请注明来源!