一、请求数据

封装http

  1. data() {
  2. return {
  3. list: [],
  4. searchPrice: [
  5. { gt: 0, lt: 100, id: 1001 },
  6. { gt: 100, lt: 500, id: 1002 },
  7. { gt: 500, lt: 1000, id: 1003 },
  8. { gt: 1000, lt: 5000, id: 1004 },
  9. { gt: 5000, lt: 10000, id: 1005 }
  10. ]
  11. goodsList:[]
  12. };
  13. },
  14. mehtods:{
  15. initData(){
  16. this.axios.get("/goods/list",{params:{start:this.start,limit:this.limit}})
  17. .then(res => {
  18. this.list = res.data.result;
  19. if(res.data.code==200){
  20. this.goodsList = res.data.result;
  21. this.total = Math.ceil(res.data.total/this.limit)*10;
  22. }
  23. });
  24. }
  25. }
  26. mounted() {
  27. this.initData(); //调用
  28. }

二、分页器

  1. <el-pagination
  2. background
  3. layout="prev, pager, next"
  4. :total="total"
  5. @current-change="getpage"
  6. ></el-pagination>
  1. data() {
  2. return {
  3. ...
  4. total:10,
  5. limit:8,
  6. start:0
  7. };
  8. },
  9. methods:{
  10. ...
  11. getpage(page){
  12. console.log(page)
  13. this.start = (page-1)*this.limit;
  14. this.initData();
  15. }
  16. ...
  17. }

三、升序降序

  1. <div class="sort">
  2. <el-button @click="handleDefault">默认</el-button>
  3. <button @click="handleSort">排序:</button>
  4. <p>价格:{{(sortFlag==1)?'↑':'↓'}}</p>
  5. </div>

排序

  1. methods:{
  2. compareUp(value){
  3. return(a,b)=>{
  4. return a[value]-b[value]
  5. }
  6. },
  7. compareDown(value){
  8. return (a,b)=>{
  9. return b[value]-a[value]
  10. }
  11. },
  12. handleSort(){
  13. this.sortFlag = (this.sortFlag==1)?-1:1
  14. if(this.sortFlag==1){
  15. this.goodsList.sort(this.compareUp("salePrice"))
  16. }else{
  17. this.goodsList.sort(this.compareDown("salePrice"))
  18. }
  19. },
  20. }

恢复默认

  1. handleDefault(){
  2. this.initData();
  3. }

四、价格分类

  1. <div class="left">
  2. <h3>通过价格搜索</h3>
  3. <div class="price" v-for="value of searchPrice" :key="value.id">
  4. <p @click="handlePrice(value.gt,value.lt)">{{value.gt}}--{{value.lt}}</p>
  5. </div>
  6. </div>
  1. data() {
  2. return {
  3. searchPrice: [
  4. { gt: 0, lt: 100, id: 1001 },
  5. { gt: 100, lt: 500, id: 1002 },
  6. { gt: 500, lt: 1000, id: 1003 },
  7. { gt: 1000, lt: 5000, id: 1004 },
  8. { gt: 5000, lt: 10000, id: 1005 }
  9. ]
  10. };
  11. }
  1. methods:{
  2. handlePrice(gt, lt) {
  3. this.axios({
  4. url: "/goods/price",
  5. methods: "get",
  6. params: {
  7. gt,
  8. lt
  9. }
  10. }).then(res => {
  11. if (res.data.code == 200) {
  12. this.goodsList = res.data.result;
  13. this.total = 10;
  14. } else {
  15. this.goodsList = [];
  16. this.$message({
  17. duration: 1000,
  18. message: res.data.msg,
  19. type: "warning"
  20. });
  21. }
  22. });
  23. },
  24. }

五、加入购物车

先写后台

models 下新建一个user.js文件

  1. var mongoose = require('./db');
  2. var UserSchema = new mongoose.Schema({
  3. userId:String,
  4. userName:String,
  5. userPwd:String,
  6. orderList:Array,
  7. cartList:Array,
  8. addressList:Array
  9. })
  10. var Users = mongoose.model('Users',UserSchema,'users');
  11. module.exports = Users;

routes 下新建一个users.js

  1. const router = require('koa-router')()
  2. const UsersModel = require('../models/user');
  3. router.prefix('/users')
  4. router.get('/',async ctx=> {
  5. var data = await UsersModel.find({})
  6. ctx.body = {
  7. code:200,
  8. msg:"请求成功",
  9. total:data
  10. };
  11. })
  12. router.post('/addCart',async ctx=>{
  13. var productId = ctx.request.body;
  14. console.log(productId)
  15. })
  16. module.exports = router

前台

  1. <button class="btn" @click="addCart(item.productId)">加入购物车</button>
  1. methods:{
  2. addCart(productId){
  3. this.axios({
  4. method:"post",
  5. url:'/users/addCart',
  6. data:{
  7. productId
  8. }
  9. }).then(res=>{
  10. console.log(res) //就可以拿到id
  11. })
  12. }
  13. }

七、登陆模块

7-1 跨域访问服务器上的cookie

//1.前端代码的配置 main.js

  1. axios.defaults.withCredentials = true
  2. axios.defaults.crossDomain = true;

//允许跨域访问cookie
//2.配置服务器 app.js

  1. app.use(cors({
  2. origin:"http://192.168.14.57:8080", //配置允许跨域的域名
  3. credentials:true
  4. }))

7-2 实现登陆功能

1.前端获取用户和密码
2.携带用户和密码向后台发送http请求
3.后端接收用户和密码
4.向数据库查询
5.将结果返回给前端
//1.前端获取用户和密码
//2.携带用户和密码向后台发送http请求

  1. <el-button type="primary" @click="handleLogin">确 定</el-button>
  2. methods:{
  3. handleLogin(){
  4. if(this.form.username && this.form.pass){
  5. this.$http({
  6. url:"/users/login",
  7. method:"post",
  8. data:{
  9. userName:this.form.username,
  10. userPwd:this.form.pass
  11. }
  12. }).then(res=>{
  13. console.log(res)
  14. })
  15. }
  16. }
  17. }

//3.后端接收用户和密码 ctx.request.body

// 登陆模块

  1. router.post('/login',async ctx=>{
  2. var data = ctx.request.body;
  3. })
  4. //4.向数据库查询
  5. router.post('/login',async ctx=>{
  6. var data = ctx.request.body;
  7. var res = await UsersModel.findOne(data);
  8. //没有的时候null 有的会返回数据
  9. console.log(res)
  10. })
  11. //5.将结果返回给前端
  12. // 登陆模块
  13. router.post('/login',async ctx=>{
  14. var data = ctx.request.body;
  15. var res = await UsersModel.findOne(data);
  16. if(res){
  17. ctx.body = {
  18. code:"200",
  19. msg:"登陆成功",
  20. successName:res.userName
  21. }
  22. }else{
  23. ctx.body = {
  24. code:"400",
  25. msg:"用户名和密码错误"
  26. }
  27. }
  28. })
  29. //前端处理代码
  30. methods:{
  31. handleLogin(){
  32. if(this.form.username && this.form.pass){
  33. this.$http({
  34. url:"/users/login",
  35. method:"post",
  36. data:{
  37. userName:this.form.username,
  38. userPwd:this.form.pass
  39. }
  40. }).then(res=>{
  41. //登陆成功
  42. if(res.data.code==200){
  43. this.$message({
  44. message:res.data.msg,
  45. duration:1000,
  46. type:"success"
  47. })
  48. this.successName = res.data.result
  49. this.dialogFormVisible = false;
  50. }else{
  51. //用户名和密码错误
  52. this.$message({
  53. duration:1000,
  54. message:res.data.msg,
  55. type:"error"
  56. })
  57. }
  58. })
  59. }else{
  60. this.$message({
  61. message:"用户名和密码不能为空",
  62. duration:1000,
  63. type:"error"
  64. })
  65. }
  66. }
  67. }

7-3 使用cookie记录登陆的状态

  1. //1.登陆成功设置cookies
  2. router.post('/login',async ctx=>{
  3. var data = ctx.request.body;
  4. var res = await UsersModel.findOne(data);
  5. if(res){
  6. ctx.cookies.set("userId",res.userId,{
  7. maxAge:1000*60*60
  8. })
  9. ctx.cookies.set("userName",res.userName,{
  10. maxAge:1000*60*60
  11. })
  12. ...
  13. })
  14. //2.配置路由检查一下登陆的状态
  15. //检查一下登陆的状态
  16. router.get('/checkLogin',async ctx=>{
  17. var userId = ctx.cookies.get("userId");
  18. if(userId){
  19. ctx.body = {
  20. code:200,
  21. msg:"登陆成功",
  22. result:ctx.cookies.get("userName")
  23. }
  24. }else{
  25. ctx.body = {
  26. code:1001,
  27. msg:"未登录"
  28. }
  29. }
  30. })
  31. //3.页面初始加载时,调用/user/checkLogin检查用户是否登陆
  32. mounted(){
  33. this.$http('/users/checkLogin').then(res=>{
  34. if(res.data.code==200){
  35. this.successName = res.data.result
  36. }else{
  37. this.$message({
  38. message:"未登陆",
  39. duration:1000,
  40. type:"warning"
  41. })
  42. }
  43. })
  44. }

7-4 退出登陆

  1. //1.配置路由 清除cookies
  2. router.post('/logout',async ctx=>{
  3. ctx.cookies.set("userId","",{
  4. maxAge:-1
  5. })
  6. ctx.cookies.set("userName","",{
  7. maxAge:-1
  8. })
  9. ctx.body ={
  10. code:200,
  11. msg:"退出登陆"
  12. }
  13. })
  14. //2.前端代码
  15. methods:{
  16. handleLogout(){
  17. this.$http.post('/users/logout').then(res=>{
  18. this.$message({
  19. message:res.data.msg,
  20. duration:1000
  21. })
  22. this.successName = ""
  23. })
  24. }
  25. }

7-5登录拦截

  1. //使用中间件
  2. //ctx.path 获取前端向后台访问的接口
  3. app.use( async (ctx,next)=>{
  4. console.log(ctx.path)
  5. // 登陆才可以访问后端其他的接口
  6. if(ctx.cookies.get("userId")){
  7. await next()
  8. }else{
  9. //没有登陆的情况后端有些接口时可以访问
  10. if(ctx.path =="/users/login" || ctx.path =="/goods/list" || ctx.path == "/users/Logout"){
  11. await next()
  12. }else{
  13. ctx.body = {
  14. code:1001,
  15. msg:"未登陆"
  16. }
  17. }
  18. }
  19. })

八、购物车模块

8-1购物车查询

  1. router.get('/cartList',async ctx=>{
  2. var data = await UsersModel.findOne({});
  3. var res = data.cartList;
  4. ctx.body ={
  5. code:200,
  6. result:res
  7. }
  8. })

8-2购物车的删除

  1. //后代代码
  2. router.post('/cartList/del',async ctx=>{
  3. var {productId} = ctx.request.body;
  4. var userId = ctx.cookies.get("userId");
  5. var data = await UsersModel.update({userId:userId},{$pull:{cartList:{productId:productId}}});
  6. if(data.ok==1){
  7. ctx.body = {
  8. code:200,
  9. msg:"删除成功"
  10. }
  11. }else{
  12. ctx.body = {
  13. code:1001,
  14. msg:"删除失败"
  15. }
  16. }
  17. })
  1. //前端代码
  2. methods:{
  3. handleDelete(productId) {
  4. console.log(productId);
  5. this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
  6. confirmButtonText: "确定",
  7. cancelButtonText: "取消",
  8. type: "warning"
  9. })
  10. .then(() => {
  11. this.$http
  12. .post("/users/cartList/del", {
  13. productId
  14. })
  15. .then(res => {
  16. console.log(res);
  17. this.initData();
  18. });
  19. })
  20. .catch(() => {});
  21. }
  22. }

8-3购物车的修改

  1. //$set
  2. //前台的代码 tips 传递item
  3. <van-stepper
  4. @change="onChange(item)"
  5. v-model="item.productNum" integer />
  1. methods:{
  2. async onChange(item){
  3. var {productNum,productId,checked} = item;
  4. await this.$http.post('/users/cartList/edit',{
  5. productNum,
  6. productId,
  7. checked
  8. })
  9. }
  10. }
  1. //后台代码
  2. router.post('/cartList/edit',async ctx=>{
  3. var {productNum,productId,checked} = ctx.request.body;
  4. var userId = ctx.cookies.get("userId");
  5. var data = await UsersModel.update(
  6. {userId:userId,"cartList.productId":
  7. productId},{$set:{
  8. "cartList.$.productNum":productNum,
  9. "cartList.$.checked":checked
  10. }});
  11. if(data.ok==1){
  12. ctx.body ={
  13. msg:"修改成功",
  14. code:200
  15. }
  16. }
  17. })

九、路由守卫

  1. Tips:一定要配置再路由地址所对应的主组件
  2. // 路由守卫
  3. beforeRouteLeave (to,from,next) {
  4. this.$http('/users/checkLogin').then(res=>{
  5. if(res.data.code == 200){
  6. next()
  7. }else{
  8. this.$message({
  9. message:res.data.msg,
  10. duration:1000
  11. })
  12. }
  13. })
  14. }
  15. };