写一个移动端(H5)的前端项目需要哪些插件以及常用的一些业务逻辑代码块,来look look 吧「干货满满」。

技术选型

使用vue-cli脚手架搭建了项目

一.首先安装node.js

Vue CLI 4.x 安装需要 nodeJs ≥ 8.9 (官方推荐 8.11.0+,你可以使用 nvm 或 nvm-windows在同一台电脑中管理多个 Node 版本)

下载安装nodeJs(和其他系统软件一样根据需求按步骤安装)这里不做介绍,
中文官方下载地址:http://nodejs.cn/download/

查看node版本:node -v

二.安装vue cli 指令

npm install -g @vue/cli

三.如果比较慢可以配置配置淘宝镜像

可以使进入项目时加载速度快一些
npm config set registry https://registry.npm.taobao.org

使用了axios实现了前后端的通信,搭配的Promise将axios进行了二次封装

安装 cnpm install axios --save

import store from '@/store/index'
// 基于环境变量配置路径
var ips = {
    
    
    development: 'http://websong.wang:4000',
    production: "http://192.168.200.23"
}
const url = ips[process.env.NODE_ENV]


// 用axios重新生成了请求的实例
const server = axios.create({
    
    
    baseURL: url, // 项目发送axios请求的公共地址
    timeout: 5000 // 请求超时时间 这里是请求超过五秒后还没有获得请求结果 提示请求超时
})
server.interceptors.request.use(config => {
    
    
    config.headers['token'] = store.state.tokenMsg.token
    return config // 将配置完成的token返回 如果不返回 请求不会继续进行
}, err => {
    
    
    Promise.reject(err) // 使用promise将错误信息返回出去
})

// axios 接受到服务器响应信息后的配置
// response 是响应的意思 这里的意思是使用响应拦截
server.interceptors.response.use(res => {
    
    
    // 每次请求完毕以后,重新获取token值:必须是在登录后才能刷新 token 过期重新请求 无痛刷新token
    if (store.state.tokenMsg.token) {
    
    
        var {
    
    
            id,
            username,
            islogin
        } = store.state.tokenMsg.user;
        axios
            .get(url + "/user/token", {
    
    
                params: {
    
    
                    uid: id, // 用户 id
                    username, // 用户名字
                    islogin, // 是否登录
                },
            })
            .then(({
     
     
                data
            }) => {
    
    
                console.log(data)
                if (data.code) {
    
    
                    // 重新吧token赋值
                    store.commit("updataToken", data.result.token);
                }
            });
    }
    // res包含了服务器返回的所有响应信息 其实就是服务器返回给你的东西
    return res.data
}, err => {
    
    
    // 当服务器响应产生错误时的回调函数
    console.error(err) // 这里将服务器发生错误的错误信息打印在控制台中
})
export default server

amfe-flexible postcss-pxtorem 实现css样式里的px转换为rem

Vant 中的样式默认使用 px 作为单位,如果需要使用 rem 单位,推荐使用以下两个工具:

postcss-pxtorem 是一款 postcss 插件,用于将 px 单位转化为 rem
lib-flexible 用于设置 rem 基准值

1.安装依赖

yarn add amfe-flexible
或者使用
npm i -S amfe-flexible

然后在 main.js 中加载执行该模块:

import 'amfe-flexible'

2.安装postcss-pxtorem依赖:

yarn add -D postcss-pxtorem
或者是
npm install postcss-pxtorem -D
这里解释一下:# -D--save-dev 的简写 把依赖包的版本信息写进 package.json 文件里面

然后在项目根目录中创建 postcss.config.js 文件:

module.exports = {
    
    
    plugins: {
    
    
        // postcss-pxtorem 插件的版本需要 >= 5.0.0
        'postcss-pxtorem': {
    
    
            rootValue({
     
      file }) {
    
     // 判断是否是vant的文件 如果是就使用 37.5为根节点字体大小
                // 否则使用75 因为vant使用的设计标准为375 但是市场现在的主流设置尺寸是750
                return file.indexOf('vant') !== -1 ? 37.5 : 75;
            },
            // 配置哪些文件中的尺寸需要转化为rem *表示所有的都要转化
            propList: ['*'],
        },
    },
};
这个文件会被自执行

vant-ui 实现的页面布局

npm i vant@latest-v2 -S

main.js 文件

引入
import Vant from 'vant';
import 'vant/lib/index.css';
Vue.use(Vant);

vue-router实现的路由导航

npm i vue-router

使用vuex解决项目数据共享,搭配vuex插件 vuex-persist 实现了本地存储

npm install --save vuex@next // 安装vuex
yarn add vuex-persistedstate --save // vuex固化工具存储本地存储的

import persist from 'vuex-persistedstate'
plugins: [persis()]
    plugins: [persist({
    
    
        storage: localStorage, // 定义数据存储的方式 值可以是localStorage 也可以是sessionStorage
        reducer(state) {
    
     //定义需要指定存储的数据 因为正常工作中vuex不是每一条数据都需要存储 所以我们需要指定需要存储的数据
            return {
    
    
                goods: state.goods
            }
        }
})]

使用lodash库扩展了方法

npm i --save lodash
node.js   var _ = require('lodash');
vue  import _ from 'lodash'

用animate.css插件库实现较为复杂的动画

网址 https://animate.style/ 
npm install animate.css // 安装
 import 'animate.css'  // 引入
 
    <transition-group 
    :duration="{ enter: 500, leave: 1000 }"
    name="animate__animated animate__bounce"
    enter-active-class="animate__zoomInDown"
    leave-active-class=" animate__zoomOutDown"
   >
// 包住组件 如果是router-view 就是transition 使用换类名即可
        // enter 进入时间 leave 离开时间
</transition-group>

使用sass作为css的预处理器

npm install --save-dev sass-loader
//sass-loader依赖于node-sass
npm install --save-dev node-sass

使用第三方dayjs插件做事件格式化的处理

npm install dayjs --save 
import dayjs from 'dayjs'
dayjs(String)
dayjs('1995-12-25')
https://blog.csdn.net/u014225733/article/details/90602290

注释插件

网址 : https://vuese.github.io/website/zh/cli/#methods
可以根据注释生成文档,可以让你养成良好的注释代码习惯,如果你按照他个规则来注释可以 快速成成文档
命令 : yarn global add @vuese/cli
在package.json中写入运行命令
  "scripts": {
    
    
    "doc": "vuese gen",
  },
运行: npm run doc
会在根目录下生成一个website 文件夹里面 有个 index.HTML 打开会有一个文档

前端的性能优化

使用cdn静态资源托管

静态资源托管网站 : https://cdn.baomitu.com/
就是把 import 导入的都给删除了然后换成 cdn 静态资源托管
  <script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script>
  <script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.5.1/vue-router.min.js"></script>
  <script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script>
  <script src="https://lib.baomitu.com/axios/0.26.0/axios.min.js"></script>
吧 vuex 和 stare 和 router 删除吧以上 cdn 放入我们的 public 里面的 index.html body标签下面即可

在 vue.config 文件夹里面写入
 return {
    
    
      externals: {
    
    
        vue: "Vue",
        "vue-router": "VueRouter",
        vuex: "Vuex",
        axios: "axios",
     },
};

vant-ui的按需引入

新建一个 piugins 文件夹里面引入 vantS.js 文件里面写入
// 一个对象向外暴露一个install 的函数
import {
    
    
    SwipeItem,
    Swipe,
} from 'vant'

var list = [ SwipeItem, Swipe ];
export default {
    
    
    install(Vue, option) {
    
    
        // vant组件的按需引入
        list.forEach((item) => {
    
    
            Vue.component(item.name, item);
        });
    },
};

// 放在  main.js 文件里面
import piugins from '../src/piugins/vantS'
Vue.use(piugins);

长列表的优化

import {
    
     throttle } from 'lodash' // 引入lodash 要不自己手写

mounted() {
    
    
		// 监听页面的滚动到底行为
		window.onscroll = throttle(() => {
    
    
			// 是否到达页底部
			var doc = document.documentElement
            /*
            scrollHeight(文档内容实际高度,包括超出视窗的溢出部分)
            scrollTop(滚动条卷进去距离)、
            clientHeight(窗口可视范围高度)
            当 clientHeight + scrollTop >= scrollHeight 时,表示已经抵达内容的底部了,可以加载更多内容。
            
            scrollHeight:可以通过 document.documentElement.scrollHeight 、document.body.scrollHeight 获取;
            clientHeight:可以通过window.innerHeight 、 document.documentElement.clientHeight 获取;
            scrollTop:可以通过window.pageYOffset 、 document.documentElement.scrollTop 获取;
            */
			if (doc.scrollHeight - 200 <= doc.clientHeight + doc.scrollTop) {
    
    
				this.$emit('onload') // 到底了
			}
		}, 1000)
},

骨架屏

在我们的数据没有加载过来的时候可以用骨架屏来站一下空白空间
封装我们的骨架屏,可以用 vant ui 的骨架屏也可以自己用 css3的动画手写骨架屏
然后在通过 vue.component 全局注册我们的组件,用v-if来做判断有数据的时候显示商品没有商品的时候显示骨架屏

<van-skeleton title row="3" />

图片懒加载自定义指令

Vue.directive('lazy', (el, bing) => {
    
    
    console.log(el)
    // new IntersectionObserver 创建我们的交叉观察器
    let ob = new IntersectionObserver(
        (changes) => {
    
    
            // changes 是个数组包含所有的监听对象和视口的交叉位置
            changes.forEach((item) => {
    
    
                if (item.isIntersecting) {
    
     //  item.isIntersecting == 1 为 true
                    //  当先监听的对象 符合条件
                    let lazyImg = item.target; // 拿到当前监听的盒子
                    // 改变src
                    el.src = bing.value;
                    // 加载完移除监听
                    ob.unobserve(lazyImg);
                }
            });
        }, {
    
    
            // threshold 控制交叉状态在什么养的情况下触发上面的回调
            threshold: [1], // 0 一露头 0.5 露一半 1 完全出现
        }
    );
    // 使`IntersectionObserver`开始监听一个目标元素。
    ob.observe(el);
})

vue.config.js 配置去掉 console.log

npm i -D terser-webpack-plugin

const {
    
     defineConfig } = require("@vue/cli-service");
const TerserPlugin = require("terser-webpack-plugin");

module.exports = defineConfig({
    
    
  // 打包后的二级目录地址
  publicPath: "/a123456",
  transpileDependencies: true,
  devServer: {
    
    
    open: true,
    port: 3000,
    // webpack项目被托管需要开启这个
    allowedHosts: "all",
  },
  // 当npm build的时候 关闭源码映射
  productionSourceMap: false,
  configureWebpack: (config) => {
    
    
    // 只有npm run build的时候 才是production
    if (process.env.NODE_ENV === "production") {
    
    
      return {
    
    
        plugins: [
          //打包环境去掉console.log
          new TerserPlugin({
    
    
            // 多进程:加速打包速度
            parallel: true,
            terserOptions: {
    
    
              ecma: undefined,
              warnings: false,
              parse: {
    
    },
              compress: {
    
    
                drop_console: true,
                drop_debugger: false,
                pure_funcs: ["console.log"], // 移除console
              },
            },
          }),
        ],
      };
    }
    // cdn托管
    return {
    
    
      externals: {
    
    
        vue: "Vue",
        "vue-router": "VueRouter",
        vuex: "Vuex",
        axios: "axios",
      },
    };
  },
});



环境变量的配置

在个目录下面新建一个 .env.development 文件 写入以下

NODE_ENV=development

在个目录下面新建一个 .env.production文件 写入以下

NODE_ENV=production
// 基于环境变量配置路径
var ips = {
    
    
    development: 'http://websong.wang:4000',
    production: "http://192.168.200.23"
}
console.log(process.env.NODE_ENV)
const url = ips[process.env.NODE_ENV]

全选和反选的逻辑

//遍历复选框
<van-checkbox
    class="checkStyle"
    v-model="item.checked"
></van-checkbox> 
<van-checkbox v-model="checkedAll">全选</van-checkbox>

checkedAll: {
    
    
      get(val) {
    
    
        return this.cartResult.every((item) => item.checked);
      },
      set(setVal) {
    
    
        this.cartResult.forEach((item) => {
    
    
          item.checked = setVal;
        });
   },
},

计算价格

  priceAll() {
    
     // reduce 计算选中的价格
      return (
        this.cartResult.reduce(
          (num, item) => (num += item.checked && item.count * item.price),
          0
        ) * 100
      );
    },

项目的业务逻辑

文件的上传显示进度条

	<!-- 进度条 -->
	<div class="pross" ref="pross"></div>

// 箭头函数
	 cutDown({
     
      file }) {
    
    
			var data = new FormData()
			data.append('inputFile', file)
			var pross = this.$refs.pross
			// 发起提交
			Axios.post('/up', data, {
    
    
				// 监听上传的进度条事件
				onUploadProgress(event) {
    
    
					var value = Math.floor((event.loaded / event.total) * 100)
					pross.innerHTML = value + '%'
					pross.style.width = value + '%'
				},
		   }).then(({
     
      data }) => {
    
    
				console.log(data)
		})
	},

vue 的过滤器的使用

// 全局过滤器
import Vue from "vue";
import day from "dayjs";
// 取小数位
Vue.filter("float", (n, set) => {
    
    
  // 1. 判断
  if (isFinite(n)) {
    
    
    return Number(n).toFixed(set || 2);
  } else {
    
    
    return n;
  }
});

// 加货币单位
Vue.filter("$", (n, $) => {
    
    
  return n + ($ || "元");
});

// 格式化时间
Vue.filter("date", (date) => {
    
    
  return day(date).format("MM-DD");
});

路由的判断

 // 需要拦截的页面 配置一个 meta 属性就可以了
  {
    
    
        path: "login",
        meta: {
    
    
          // 有true表示需要登录才能看
          auth: false,
        },
        component: () => import("@/views/User/Login"),
  },

// 全局的前置路由守卫--路由的拦截器--路由的生命周期--路由的钩子函数
router.beforeEach((to, from, next) => {
    
    
  // next 有几种用法:字符串地址,对象,布尔值 无论怎样next必须执行
  var token = store.getters.token;
  var auth = to.meta.auth;
  // 如果需要登录,并且登录了,让它进入
  if ((token && auth === true) || (!token && auth === false)) {
    
    
    next();
    // 如果登录了,不需要登录才能访问,则不让进入
  } else if ((token && auth === false) || (!token && auth === true)) {
    
    
    next(false);
    // 没有登录,不需要登录才能访问,则让进入
  } else {
    
    
    next();
  }
});
// 路由后置守卫
router.afterEach((to, from) => {
    
    
  // 预先请求数据
  // 上传日志:用户的操作行为,用户是从哪个时间点进入这个页面的。
});

根据权限限制点击拦截

第一步:写一个v-off 指令传一个
// tabBar 拦截 
 <van-tabbar-item
        v-off="{
    
    
          to: to,
          path: '/User',
        }"
        to="/User"
        icon="setting-o"
        >我的</van-tabbar-item
      >
</van-tabbar>


  methods: {
    
    
    to(path) {
    
    
      this.$router.push(path);
    },
  },

// 指令是有生命周期的
Vue.directive("isLogin", {
    
    
  // 挂载完成
  inserted(el, bing) {
    
    
    el.addEventListener("click", (e) => {
    
    
      // 判断一下是否有登录的记录
      if (store.state.userInfo.token) {
    
    
        // 这里是灵活的,自己定义的
        var {
    
     action, path } = bing.value;
        action(path);
      } else {
    
    
        // 如果没有登录,提示用户去登录
        Dialog.confirm({
    
    
          title: "提示",
          message: "您需要先登录才能继续操作,是否去登录?",
        })
          .then(() => {
    
    
            router.push("/user/login");
          })
          .catch(() => {
    
    
            // on cancel
          });
      }
      // 如果没有就停止继续
    });
  },
});

动态路由

动态路由是什么?
一般我们使用vue-router配置路由时,都是直接配置固定的路径
而动态路由是我们可以在 vue-router 的路由路径中使用“动态路径参数”
让路径不再是固定的。


比如在写一个商品详情页面的时候,我们的页面结构都一样,只是渲染的数据不同而已,这时候就可以根据商品的不同id去设置动态路由,只需要写一个组件,就可以把每个商品的商品详情映射到同一个组件上去。
首先我会在 router 的配置项里面
const routes = [
  {
    
    
    path: "/",
    component: () => import("@/views/Main.vue"),
    redirect: "/index",
    children: [
      {
    
    
        path: "/index/:id",
        component: () => import("@/views/Index.vue"),
      },
    ],
  },
];
超级重点:一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。

methods: {
    
    
    goPage(val) {
    
    
      this.state = val;
      this.$router.push({
    
    
        path: "/index2/" + val,
      });
    },
},

客服的sockit长链接

webSocket 的概念
webSocket 协议是基于TCP的一种新的网络协议,它实现了浏览器与服务器全双工网络通信 允许服务器主动发送信息给客户端,可以实时连接
websocket 是一种持久的协议,http是非持久协议,也就是长链接

早期的话通信:a向服务器发送一次消息,服务器就是每隔1秒就向服务器发送一次请求,看看有没有a的消息,如果有a的消息就拿过来没有就一直请求 非常消耗性能
 
原生的 websocket 比较的麻烦 而且只能传字符串 不能传对象还得来回转换,方法也很少,比如广播事件都没有,还得自己封装 (自封封装还是通过便利)
安装的地址 https://www.npmjs.com/package/nodejs-websocket
安装依赖 npm install nodejs-websocket


现在用的是 socketio
> npm install express@4
> npm install socket.io
// 一上来用他来监听

//  第一步 先导入我们的 socket.io 模块 在去 new Server(server);  后端可以用 io.on 监听客户端发来的数据 用 emit 来派发给前端数据

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const {
    
    
    Server
} = require("socket.io");
const io = new Server(server);

app.get('/', (req, res) => {
    
    
    res.sendFile(__dirname + '/index.html');
});

// 一上来用他来监听
io.on('connection', (socket) => {
    
    
    console.log('a user connected');

    // 后端监听传来的消息
    socket.on('hi', (msg) => {
    
    
        console.log(msg)
        // 向前端发送信息
        socket.emit('say', {
    
    
            say: '你在说什么小伙子'
        })
    })
});

server.listen(3000, () => {
    
    
    console.log('listening on *:3000');
});


// 连接服务端
var arr = []
var socket = io();
 let input = document.querySelector('#input')
 btn.addEventListener('click', function () {
    
    

 // 向服务器发起一个 socket 消息
socket.emit('hi', {
    
    
     // to:'', 可以指定告诉人
      msg: input.value

})
socket.on('say', (say) => {
    
    
     console.log(say)
     arr.push(say)
})
sm.innerHTML(
     `
      <div>wda</div>
      `
   )
})

js调节移动端响应式的屏幕尺寸

1.设置当前html文件的字符编码
<meta charset="UTF-8">
<!-- 设置浏览器的兼容模式(让IE使用最新的浏览器渲染) -->
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<!--  视口(快捷键:meta:vp) -->
<meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"/>
<!--  Cache-Control头域  Cache-Control指定请求和响应遵循的缓存机制。 -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"/>
是用于设定禁止浏览器从本地机的缓存中调阅页面内容,设定后一旦离开网页就无法从Cache中再调出
 <meta http-equiv="Pragma" content="no-cache"/>
禁止将页面中的一连串数字识别为电话号码、并设置为手机可以拨打的一个连接。这个标签的默认值是telephone=yes。
 <meta content="telephone=no" name="format-detection"/>
7.删除默认的苹果工具栏和菜单栏 当我们需要显示工具栏和菜单栏时,这个行meta就不用加了,默认就是显示。
  <meta content="yes" name="apple-mobile-web-app-capable"/>
8.控制状态栏显示样式 content设置状态栏颜色
 <meta content="black" name="apple-mobile-web-app-status-bar-style"/>
.条件注释
<!--[if lt IE 9]>
<script src="lib/html5shiv/html5shiv.min.js"></script>
<script src="lib/respond/respond.min.js"></script>
<![endif]-->

- html5shiv让浏览器可以识别html5的新标签;
- respond让低版本浏览器可以使用CSS3的媒体查询。

纯前端模糊搜索防抖

先把 数据备份一份 也就是在复制一份  arr渲染的数据  arr1 备份数据  searchValue 搜索的value
arr = arr1.filter(item => searchValue.includes(item.name)) 

文件的上传

文件上传的底层原理
<input type="file" @change="upload" />
input type 的file 属性  原生 input 拿到这个 file.target.files[0] 上传
vant 的文件上传
<van-uploader accept="*" :after-read="afterRead" />	

afterRead( {
     
     file} ) {
    
     // vant 的是
			// 此时可以自行将文件上传至服务器
			// 先判断大小
			if (file.size / 1024 >= 30) {
    
    
				return alert('超出30kb了')
			} 
			// 类型判断
			if (!/image/.test(file.type)) {
    
    
				return alert('类型不允许')
			} 
			// 重点:上传文件使用formData
			var data = new FormData()
			data.append('inputFile', file)
			var pross = this.$refs.pross
			// 发起提交
			Axios.post('/up', data, {
    
    
				// axios第三个参数是可以监听 上传的进度条事件
				onUploadProgress(event) {
    
    
					var value = Math.floor((event.loaded / event.total) * 100)
					pross.innerHTML = value + '%' // 设置倒计时
					pross.style.width = value + '%' // 写一个div设置width 度
				},
			}).then(({
     
      data }) => {
    
    
				console.log(data)
			})
},

项目中碰到的问题

props的返回值

	list: {
    
    
			// 约束类型
			type: Array,
			// 可以设置默认值
			// 如果值类型是对象或数组,需要使用函数返回
			default: function () {
    
    
				return []
			},
	},

keep-alive 的缓存问题太深的组件嵌套失效了

<!--TODO:问题 keep-alive 不能缓存多级嵌套,需要加key -->
	<!-- <keep-alive>
	<router-view :key="$route.fullPath" />
</keep-alive> -->

路由跳转报错

重复性跳转

[email protected]版本及以上回调形式已经改成promise api的形式了,返回的是一个promise,如果路由地址跳转相同, 且没有捕获到错误,控制台始终会出现如图所示的警告 (注:3.0以下版本则不会出现以下警告!!!,因路由回调问题…)

// 重写 push 结局跳转不传参报错的问题
import VueRouter from "vue-router";
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
    
    
  return originalPush.call(this, location).catch((err) => err);
};

配置 websocket 安装

直接安装是安装不上的

在package.json 里面配置

“socket.io-client”: “2.3.0”,

在执行 npm i

.git文件删除怎么了

1、我们找到原来的项目,

2、把原来之前的项目给 clone 下来

3、克隆下来之后,把原来之前的 .git 文件给剪切然后 再放到没有 .git 的文件里

远程仓库的路径做更改,git提交远程提交不上

$ git push 报错
[session-4b46a982] Auth error: Access deined: authorize failure.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

git remote -v 查看提交的地址 改掉

找到git的配置文件

在找到 config 配置文件把他的

改一下 origin 里的 url 你的更改后的项目地址

后端node

用 node.js 和 expres 框架搭建一个小服务器

//require表示引包,引包就是引用自己的一个特殊功能
 var http = require("http");  
 var url = require("url");
 var server = http.createServer(function(req,res){
    
    
    //得到查询部分,由于写了true,那么就是一个对象
     var queryObj = url.parse(req.url,true).query;
     var name = queryObj.name;
     var age = queryObj.age;
     var sex = queryObj.sex;
     res.writeHead(200,{
    
    "Content-Type":"text/html;charset=UTF-8"});
     res.end("服务器收到了表单请求" + name + age + sex);
 });
 
 //运行服务器,监听3000端口(端口号可以任改)
 server.listen(3000,"127.0.0.1");
 
 // 终端打印如下信息
 console.log('Server running at http://127.0.0.1:3000/')

后端全选删除接口

/*
   第一步用 req.query 拿到前端发送过来的数据
   用 remove 删除 指定的id  只要满足$in 拿 [] 里面的元素 都可以查询出来 查询出来删除
*/

const {
    
    
    addGoods
} = require('../DB')
module.exports = function (router) {
    
    
    router.post('/', (req, res) => {
    
    
        let
            txt = req.body
        console.log(txt)
        addGoods.remove({
    
    
            _id: {
    
    
                $in: txt
            },
        }).then(() => {
    
    
            res.send({
    
    
                code: 200,
                msg: '删除购物车成功',
            })
        }).catch(() => {
    
    
            res.send({
    
    
                code: 404,
                msg: '删除购物车失败',
            })
        })
    })
    return router
}

登录的接口

1.下载我们的 jsonwebtoken 	包
用send 发送到前端 
    token: jwt.sign({
    
    
        uid: data._id
         }, pub, {
    
    
         expiresIn: '.5h'
      })
      
      const {
    
    
    db_list
} = require('../DB')
2 当用户输入账号和密码发送到服务端 我用 find 在我们的 mongoodb 数据库去查找我们的数据如果查找到的就返回我们前端数据 把 token范过期,这里用 jwt.verify判断token是否解密成功  解密成功 用try catch  
// 首先引入我们的 token 包
var jwt = require('jsonwebtoken');

// 自己写一个类似于密码的东西
var pub = 'asodh23hdhhodh9sahdosahdhsadhsfhdsofodsfh'


module.exports = function (router) {
    
    
    router.get('/', (req, res) => {
    
    
        // req.get 是可以拿到前端 headers 请求头的数据
        // jwt.verify 把前端headers里面传过来的一个token进行解密
        console.log(req.get('token'))
        // try {
    
    
        //     jwt.verify(req.get('token')) // 如果解密成功就会返回一个  {}
        // } catch (e) {
    
    
        //     // 如果没有 token 就 try catch 给他抛出去
        //     res.json({
    
    
        //         error: e
        //     })
        // }
        // goods 是你上面定义的字段根据这个查找
        db_list.find({
    
    
            username: req.query.username,
            password: req.query.password,
        }).then((data) => {
    
    
            // 判断返回的数据 是否有长度如果有长说明找到了
            if (data.length > 0) {
    
    
                res.send({
    
    
                    code: 200,
                    msg: '登录成功',
                    //   expiresIn1 表示一个小时 然后 .5h 是表示半个小时
                    //   pub 自己设置的密码
                    //   返回的 id  data._id
                    token: jwt.sign({
    
    
                        uid: data._id
                    }, pub, {
    
    
                        expiresIn: '.5h'
                    })

                })
            } else {
    
    
                res.send({
    
    
                    code: 404,
                    msg: '登录失败,该用户不存在',
                })
            }

        })

    })
    return router
}

注册的接口

let {
    
    
    db_list
} = require('../DB')


module.exports = function (router) {
    
    
    router.get('/', (req, res) => {
    
    
        console.log(req)
        db_list.find({
    
    
            username: req.query.username
        }).then((data) => {
    
    
            console.log(data)
            //  说明找到可
            if (data.length > 0) {
    
    
                res.send({
    
    
                    code: 405,
                    msg: '该用户名已经注册',
                })
            } else {
    
    
                // goods 是你上面定义的字段根据这个查找
                db_list.create(req.query).then(() => {
    
    
                    res.send({
    
    
                        code: 200,
                        msg: '注册成功',
                    })
                }).catch(() => {
    
    
                    res.send({
    
    
                        code: 404,
                        msg: '注册失败',
                    })
                })
            }

        })
    })
    return router
}

修改用户的接口

let {
    
    
    order
} = require('../DB')



module.exports = function (router) {
    
    
    router.get('/', (req, res) => {
    
    
        // 修改商品的接口
        order.update({
    
    
            _id: req.query._id
        }, {
    
    
            $set: req.query
        }).then(() => {
    
    
            res.send({
    
    
                state: 200,
                success: true,
                message: '修改商品成功'
            })
        }).catch(() => {
    
    
            res.send({
    
    
                state: 404,
                success: false,
                message: "修改商品成功"
            })
        })
    })
    return router
}

搜索商品

const {
    
    
    goods
} = require('../DB')


module.exports = function (router) {
    
    
    router.get('/', async (req, res) => {
    
    
        // goods 是你上面定义的字段根据这个查找
        let reg = new RegExp(req.query.goods_name)
        var data = await goods.find({
    
    
            goods_name: reg
        })
        if (data) {
    
    
            res.send({
    
    
                result: data,
                code: 200,
                msg: '查找成功',
            })
        } else {
    
    
            res.send({
    
    
                code: 404,
                msg: '查找失败',
            })
        }
    })
    return router
}

项目的代码地址

全栈移动段项目

猜你喜欢

转载自blog.csdn.net/qq_54753561/article/details/127245069
今日推荐