一、请求数据
封装http
data() {return {list: [],searchPrice: [{ gt: 0, lt: 100, id: 1001 },{ gt: 100, lt: 500, id: 1002 },{ gt: 500, lt: 1000, id: 1003 },{ gt: 1000, lt: 5000, id: 1004 },{ gt: 5000, lt: 10000, id: 1005 }]goodsList:[]};},mehtods:{initData(){this.axios.get("/goods/list",{params:{start:this.start,limit:this.limit}}).then(res => {this.list = res.data.result;if(res.data.code==200){this.goodsList = res.data.result;this.total = Math.ceil(res.data.total/this.limit)*10;}});}}mounted() {this.initData(); //调用}
二、分页器
<el-paginationbackgroundlayout="prev, pager, next":total="total"@current-change="getpage"></el-pagination>
data() {return {...total:10,limit:8,start:0};},methods:{...getpage(page){console.log(page)this.start = (page-1)*this.limit;this.initData();}...}
三、升序降序
<div class="sort"><el-button @click="handleDefault">默认</el-button><button @click="handleSort">排序:</button><p>价格:{{(sortFlag==1)?'↑':'↓'}}</p></div>
排序
methods:{compareUp(value){return(a,b)=>{return a[value]-b[value]}},compareDown(value){return (a,b)=>{return b[value]-a[value]}},handleSort(){this.sortFlag = (this.sortFlag==1)?-1:1if(this.sortFlag==1){this.goodsList.sort(this.compareUp("salePrice"))}else{this.goodsList.sort(this.compareDown("salePrice"))}},}
恢复默认
handleDefault(){this.initData();}
四、价格分类
<div class="left"><h3>通过价格搜索</h3><div class="price" v-for="value of searchPrice" :key="value.id"><p @click="handlePrice(value.gt,value.lt)">{{value.gt}}--{{value.lt}}</p></div></div>
data() {return {searchPrice: [{ gt: 0, lt: 100, id: 1001 },{ gt: 100, lt: 500, id: 1002 },{ gt: 500, lt: 1000, id: 1003 },{ gt: 1000, lt: 5000, id: 1004 },{ gt: 5000, lt: 10000, id: 1005 }]};}
methods:{handlePrice(gt, lt) {this.axios({url: "/goods/price",methods: "get",params: {gt,lt}}).then(res => {if (res.data.code == 200) {this.goodsList = res.data.result;this.total = 10;} else {this.goodsList = [];this.$message({duration: 1000,message: res.data.msg,type: "warning"});}});},}
五、加入购物车
先写后台
models 下新建一个user.js文件
var mongoose = require('./db');var UserSchema = new mongoose.Schema({userId:String,userName:String,userPwd:String,orderList:Array,cartList:Array,addressList:Array})var Users = mongoose.model('Users',UserSchema,'users');module.exports = Users;
routes 下新建一个users.js
const router = require('koa-router')()const UsersModel = require('../models/user');router.prefix('/users')router.get('/',async ctx=> {var data = await UsersModel.find({})ctx.body = {code:200,msg:"请求成功",total:data};})router.post('/addCart',async ctx=>{var productId = ctx.request.body;console.log(productId)})module.exports = router
前台
<button class="btn" @click="addCart(item.productId)">加入购物车</button>
methods:{addCart(productId){this.axios({method:"post",url:'/users/addCart',data:{productId}}).then(res=>{console.log(res) //就可以拿到id})}}
七、登陆模块
7-1 跨域访问服务器上的cookie
//1.前端代码的配置 main.js
axios.defaults.withCredentials = trueaxios.defaults.crossDomain = true;
//允许跨域访问cookie
//2.配置服务器 app.js
app.use(cors({origin:"http://192.168.14.57:8080", //配置允许跨域的域名credentials:true}))
7-2 实现登陆功能
1.前端获取用户和密码
2.携带用户和密码向后台发送http请求
3.后端接收用户和密码
4.向数据库查询
5.将结果返回给前端
//1.前端获取用户和密码
//2.携带用户和密码向后台发送http请求
<el-button type="primary" @click="handleLogin">确 定</el-button>methods:{handleLogin(){if(this.form.username && this.form.pass){this.$http({url:"/users/login",method:"post",data:{userName:this.form.username,userPwd:this.form.pass}}).then(res=>{console.log(res)})}}}
//3.后端接收用户和密码 ctx.request.body
// 登陆模块
router.post('/login',async ctx=>{var data = ctx.request.body;})//4.向数据库查询router.post('/login',async ctx=>{var data = ctx.request.body;var res = await UsersModel.findOne(data);//没有的时候null 有的会返回数据console.log(res)})//5.将结果返回给前端// 登陆模块router.post('/login',async ctx=>{var data = ctx.request.body;var res = await UsersModel.findOne(data);if(res){ctx.body = {code:"200",msg:"登陆成功",successName:res.userName}}else{ctx.body = {code:"400",msg:"用户名和密码错误"}}})//前端处理代码methods:{handleLogin(){if(this.form.username && this.form.pass){this.$http({url:"/users/login",method:"post",data:{userName:this.form.username,userPwd:this.form.pass}}).then(res=>{//登陆成功if(res.data.code==200){this.$message({message:res.data.msg,duration:1000,type:"success"})this.successName = res.data.resultthis.dialogFormVisible = false;}else{//用户名和密码错误this.$message({duration:1000,message:res.data.msg,type:"error"})}})}else{this.$message({message:"用户名和密码不能为空",duration:1000,type:"error"})}}}
7-3 使用cookie记录登陆的状态
//1.登陆成功设置cookiesrouter.post('/login',async ctx=>{var data = ctx.request.body;var res = await UsersModel.findOne(data);if(res){ctx.cookies.set("userId",res.userId,{maxAge:1000*60*60})ctx.cookies.set("userName",res.userName,{maxAge:1000*60*60})...})//2.配置路由检查一下登陆的状态//检查一下登陆的状态router.get('/checkLogin',async ctx=>{var userId = ctx.cookies.get("userId");if(userId){ctx.body = {code:200,msg:"登陆成功",result:ctx.cookies.get("userName")}}else{ctx.body = {code:1001,msg:"未登录"}}})//3.页面初始加载时,调用/user/checkLogin检查用户是否登陆mounted(){this.$http('/users/checkLogin').then(res=>{if(res.data.code==200){this.successName = res.data.result}else{this.$message({message:"未登陆",duration:1000,type:"warning"})}})}
7-4 退出登陆
//1.配置路由 清除cookiesrouter.post('/logout',async ctx=>{ctx.cookies.set("userId","",{maxAge:-1})ctx.cookies.set("userName","",{maxAge:-1})ctx.body ={code:200,msg:"退出登陆"}})//2.前端代码methods:{handleLogout(){this.$http.post('/users/logout').then(res=>{this.$message({message:res.data.msg,duration:1000})this.successName = ""})}}
7-5登录拦截
//使用中间件//ctx.path 获取前端向后台访问的接口app.use( async (ctx,next)=>{console.log(ctx.path)// 登陆才可以访问后端其他的接口if(ctx.cookies.get("userId")){await next()}else{//没有登陆的情况后端有些接口时可以访问if(ctx.path =="/users/login" || ctx.path =="/goods/list" || ctx.path == "/users/Logout"){await next()}else{ctx.body = {code:1001,msg:"未登陆"}}}})
八、购物车模块
8-1购物车查询
router.get('/cartList',async ctx=>{var data = await UsersModel.findOne({});var res = data.cartList;ctx.body ={code:200,result:res}})
8-2购物车的删除
//后代代码router.post('/cartList/del',async ctx=>{var {productId} = ctx.request.body;var userId = ctx.cookies.get("userId");var data = await UsersModel.update({userId:userId},{$pull:{cartList:{productId:productId}}});if(data.ok==1){ctx.body = {code:200,msg:"删除成功"}}else{ctx.body = {code:1001,msg:"删除失败"}}})
//前端代码methods:{handleDelete(productId) {console.log(productId);this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning"}).then(() => {this.$http.post("/users/cartList/del", {productId}).then(res => {console.log(res);this.initData();});}).catch(() => {});}}
8-3购物车的修改
//$set//前台的代码 tips 传递item<van-stepper@change="onChange(item)"v-model="item.productNum" integer />
methods:{async onChange(item){var {productNum,productId,checked} = item;await this.$http.post('/users/cartList/edit',{productNum,productId,checked})}}
//后台代码router.post('/cartList/edit',async ctx=>{var {productNum,productId,checked} = ctx.request.body;var userId = ctx.cookies.get("userId");var data = await UsersModel.update({userId:userId,"cartList.productId":productId},{$set:{"cartList.$.productNum":productNum,"cartList.$.checked":checked}});if(data.ok==1){ctx.body ={msg:"修改成功",code:200}}})
九、路由守卫
Tips:一定要配置再路由地址所对应的主组件// 路由守卫beforeRouteLeave (to,from,next) {this.$http('/users/checkLogin').then(res=>{if(res.data.code == 200){next()}else{this.$message({message:res.data.msg,duration:1000})}})}};
