day-060-sixty-20230428-vue项目
vue项目
配置开发服务器
-
如果没有后端接口,可以直接通过浏览器控制台看到别人网站的接口。
- Shift+Control+I打开浏览器控制台,点击Network查看网络请求,点击Fetch/XHR,查看当前页面发送的请求。
- 触发请求,可以看到浏览器向别人的后端发送的请求及请求信息。
- 复制一下请求路径和请求方式及入参,提取如
http://backend-api-01.newbee.ltd/api/v1/index-infos
的url,最好一个网站仅用http://backend-api-01.newbee.ltd
,即取协议到端口处,为一个代理地址的target属性。对应名可以用拼音进行分类,比如取二级域名newbee
并在前面加一个斜线,为代理地址名。即确定用/newbee
代理http://backend-api-01.newbee.ltd
,也可以用自定义的如/NewPeak/
代理http://backend-api-01.newbee.ltd
。为了表示兼容和具体通用流程,这里用/NewPeak/
表示。
-
在
/vue.config.js
中修改const { defineConfig } = require("@vue/cli-service"); module.exports = defineConfig({ devServer: { proxy: { // 1. 以用户发起一个请求时的url为目标路径。 // 2. 将以`/NewPeak/`开头的目标路径为触发该代理的时机。 "/NewPeak/": { target: "http://backend-api-01.newbee.ltd", // 3. 将会以`/NewPeak/`开头的目标路径添加到其开头。 ws: true, //是否代理websockets。 changeOrigin: true, //4. 是否伪装访问源,一般选true,否则可能请求不了。 pathRewrite: { "^/NewPeak/": "/" }, //5. 目标路径重写。替换url,缩短原的旧标识。 // pathRewrite:path=>path.replace(/^\/NewPeak\//, "/"),//目标路径重写-函数方式。 // pathRewrite(path, req) {//目标路径重写-全入参。 // console.log("path", path, `;${path.replace(/^\/NewPeak\//, "/")}`); // //debugger // // console.dir(req, { deep: 1 }); // // console.log("req", req); // return path.replace(/^\/NewPeak\//, "/"); // }, }, "/api": { // /api-->http://backend-api-01.newbee.ltd/api target: "http://backend-api-01.newbee.ltd", ws: true, changeOrigin: true, }, }, }, });
-
重启项目,以便让配置生效。
-
在项目中任意地方用
/NewPeak/
发起一个请求。fetch("/NewPeak/api/v1/index-infos")//相当于fetch(`http://backend-api-01.newbee.ltd/api/v1/index-infos`) /* //fetch("/NewPeak/api/v1/index-infos") --> 目标路径为`/NewPeak/api/v1/index-infos` --> `/NewPeak/`触发了`/vue.config.js`中的`module.exports.devServer.proxy["/NewPeak/"]` --> module.exports.devServer.proxy["/NewPeak/"].target + module.exports.devServer.proxy["/NewPeak/"].pathRewrite(`/NewPeak/api/v1/index-infos`) --> `http://backend-api-01.newbee.ltd` + `/NewPeak/api/v1/index-infos`.replace(/^\/NewPeak\//, "/") --> `http://backend-api-01.newbee.ltd` + `/api/v1/index-infos` --> `http://backend-api-01.newbee.ltd/api/v1/index-infos`; */
配置axios
-
安装axios
npm i axios
-
新建
/src/http/http.js
用于对axios进行二次封装文件与/src/http/index.js
调用二次封装过后的axios进行接口请求,把所有的axios都封装并导出。- 一般是实例化一个axios实例对象出来,但这里直接对axios的原型做了处理。
-
/src/http/http.js
// axios 二次封装文件 import axios from "axios"; //配置基础路径 axios.defaults.baseURL=process.env.NODE_ENV==="production"?"XXXX":"/api/v1";// 真实项目中baseURL分开发环境和生产环境 //生产环境 production //开发环境 development---目前 // 添加请求拦截器 axios.interceptors.request.use(function (config) { // 在发送请求之前做些什么 let token=localStorage.getItem("xfdata"); if(token){ config.headers.token=token; } return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); }); // 添加响应拦截器 axios.interceptors.response.use(function (response) { return response.data; }, function (error) { // 超出 2xx 范围的状态码都会触发该函数。 // 对响应错误做点什么 return Promise.reject(error); }); export default axios;
-
/src/http/index.js
import http from "./http.js"; // 拿到首页数据 - http://backend-api-01.newbee.ltd/api/v1/index-infos function getHomeData() { return http.get("/index-infos"); } export default { getHomeData, };
-
- 一般是实例化一个axios实例对象出来,但这里直接对axios的原型做了处理。
-
在
/src/main.js
中导出/src/http/index.js
中的axios接口函数集合对象,并挂载到vue原型上,以便可以在vue组件内通过this. x x x 访问到 a x i o s 接口函数集合对象,并通过 ‘ t h i s . xxx访问到axios接口函数集合对象,并通过`this. xxx访问到axios接口函数集合对象,并通过‘this.集合对象名.接口名访问到二次封装后axios的请求函数,如
this.$api.register`。-
/src/main.js
import Vue from "vue"; import api from "./http/index.js";//可以通过this.$api.xxx()调用`/src/http/index.js`中的xxx方法。 Vue.prototype.$api = api;
-
组件抽离思路
对于差不多一致的页面,可以抽离出一个组件,进而那几个地方复用该组件。
静态文件
- 组件中要调用的静态文件,一般放在文件夹
/src/assets/
中,因为这些文件不一定要调用。- 因为组件有些是懒加载的,组件都不加载,那就不一定会用到了。
- 一般网站及的静态文件,放在
/public/
中。如/public/index.html
模板或/public/favicon.ico
图标。
配置前端验证码
-
安装vue2-verify插件。
- 有很多前端验证插件,这里选vue2-verify;
- vue2-verify - npm插件
npm i vue2-verify
- 有很多前端验证插件,这里选vue2-verify;
-
在要使用的组件中引入并使用vue2-verify。
<template> <Verify @success="alert('success')" @error="alert('error')" :type="1"></Verify> </template> <script> import Verify from 'vue2-verify' export default { components: { Verify }, methods: { alert(text) { console.log(text) } }, } </script>
-
修改Verify组件的一些参数,以得到自己想要的功能类型。
<template> <Verify :type="2" :showButton="false" fontSize="18px"></Verify> </template>
-
修改verify组件的样式,以得到自己想要的样式。
<template> <Verify @success="handleAlert('success')" @error="handleAlert('error')" :type="2" :showButton="false" fontSize="18px"></Verify> </template> <script> import Verify from 'vue2-verify' export default { components: { Verify }, methods: { handleAlert(text) { console.log(text) } }, } </script> <style lang="less"> .cerify-code-panel { margin-top: 20px; margin-left: 15px; display: flex; .verify-code { width: 130px !important; height: 42px !important; line-height: 42px !important; } .verify-code-area { display: flex; .varify-input-code { height: 40px; line-height: 40px; width: 100px; margin-left: 10px; border: 1px solid #eee; font-size: 16px; text-indent: 10px; } .verify-change-code { font-size: 14px; } } } </style>
配置加密md5
-
安装js-md5插件。
- 有很多前端验证插件,这里选js-md5;
- js-md5 - npm插件
npm i js-md5
- 有很多前端验证插件,这里选js-md5;
-
在需要使用md5加密的文件中引入并使用md5加密。
-
/src/http/index.js
import http from "./http.js"; import md5 from "js-md5"; // 登录接口 - http://backend-api-01.newbee.ltd/api/v1/user/login function login(loginName, password) { return http.post("/user/login", { loginName, passwordMd5: md5(password) }); } export default { login, };
-
token值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ja2JAnb0-1682697499587)(./后端返回的token的使用思路.png)]
- token的概念
- token是后端依据算法生成的用来表示用户登录信息的一堆字符串,它标识了用户的身份。类似于用户名及临时密码。
- 有很多接口需要附带token信息才能拿到数据。可以理解为,有了token,在后端那边就相当于有了身份标识,后端就可以确定是那个人请求的接口,以及知道那个是是否有权限访问一些数据。
- token是后端依据算法生成的用来表示用户登录信息的一堆字符串,它标识了用户的身份。类似于用户名及临时密码。
- token在应用的整个流程思路
- 前端用户发起登录的请求,附带用户名及加密密码。
- 前端登录请求到达后端,后端根据前端的数据,判断前端用户是否登录成功。同时用一个算法得出token信息,如果用户名及密码正确,就返回token信息给前端。
- 前端得到token,把token存在于浏览器本地存储及vuex或全局变量或cookie等地方。并提示登录成功的相关操作,如跳转页面等。
- 这个得看具体需求,如果需要刷新后依旧可以访问,那就只能存在于浏览器本地存储或cookie中。
- 前端在有token的情况下,为后续每一个请求都附加上token信息。
- 其实可以只对特定的请求做单独处理,即有些请求放token,有些不放。但那样太麻烦,因为token在目前的前后端交互中是核心数据,一般每个请求都要写的。
- 所以一般是每个请求都附带上token。因为有些请求,不一定能附加信息,如get请求或delete请求这一类,而token一般都要附带。故而放在
请求头Response headers
中比较合理。- 而统一对请求头做处理,axios中有一个钩子函数,即请求拦截器
axios.interceptors.request.use()
。
- 而统一对请求头做处理,axios中有一个钩子函数,即请求拦截器
- 所以一般是每个请求都附带上token。因为有些请求,不一定能附加信息,如get请求或delete请求这一类,而token一般都要附带。故而放在
- 其实可以只对特定的请求做单独处理,即有些请求放token,有些不放。但那样太麻烦,因为token在目前的前后端交互中是核心数据,一般每个请求都要写的。
- 如果请求过程中,发现token有问题,那么可以把token清空,并重定向到登录页,让用户登录一下。
- 具体是什么时候有问题,一般是后端发现的,这个逻辑主要也是后端来做。
- 可以在想要接口中做这个处理,也可以每个接口都处理。但麻烦。
- 一般是每个接口都做,如果后端返回的code为某个值如code或resultCode为416之类的,就约定要进行清空token等操作。
- 而统一对响应头做处理,axios中有一个钩子函数,即响应拦截器
axios.interceptors.response.use()
。
- 而统一对响应头做处理,axios中有一个钩子函数,即响应拦截器
- 一般是每个接口都做,如果后端返回的code为某个值如code或resultCode为416之类的,就约定要进行清空token等操作。
- 步骤
-
在登录页
/src/views/LoginView.vue
做登录操作,并处理登录成功的场景-
/src/views/LoginView.vue
核心<template> <div class="login-wrap"> <van-nav-bar :title="flag ? `登录` : `注册`" left-arrow> <template #right> <van-icon name="ellipsis" size="18" /> </template> </van-nav-bar> <div class="img-box"> <img src="../assets/logo.png" alt="" /> </div> <van-form @submit="onSubmit()"> <van-field v-model="username" name="用户名" label="用户名" placeholder="用户名" :rules="[{ required: true, message: '请填写用户名' }]" /> <van-field v-model="password" type="password" name="密码" label="密码" placeholder="密码" :rules="[{ required: true, message: '请填写密码' }]" /> <div style="margin: 16px"> <van-button round block type="info" native-type="submit"> {{ flag ? `登录` : `注册` }} </van-button> </div> </van-form> </div> </template> <script> import Verify from "vue2-verify"; import { Notify } from "vant"; export default { components: { Verify, }, data() { return { username: "", password: "", flag: true, verifyFlag: false, }; }, methods: { onSubmit() { this.$api .login(this.username, this.password) .then((value) => { // {"resultCode":200,"message":"SUCCESS","data":"a98cd1e0376b20776dcfb6ff8306031e"} console.log(value); let { resultCode, message, data } = value; if (resultCode !== 200) { Notify(message || "登录出错,请重试"); this.$refs.theVerify.refresh(); return; } this.username = this.password = ``; Notify({ type: "success", message: "登录成功" }); if (data) { localStorage.setItem("xfAppToken", data); } this.$router.push("/IndexView"); }) .catch((error) => { console.log(`error-->`, error); }) .finally(() => { console.log("登录操作后执行"); this.$refs.theVerify.refresh(); }); }, }, }; </script>
-
/src/views/LoginView.vue
全部<template> <div class="login-wrap"> <van-nav-bar :title="flag ? `登录` : `注册`" left-arrow> <template #right> <van-icon name="ellipsis" size="18" /> </template> </van-nav-bar> <div class="img-box"> <img src="../assets/logo.png" alt="" /> </div> <van-form @submit="onSubmit()"> <van-field v-model="username" name="用户名" label="用户名" placeholder="用户名" :rules="[{ required: true, message: '请填写用户名' }]" /> <van-field v-model="password" type="password" name="密码" label="密码" placeholder="密码" :rules="[{ required: true, message: '请填写密码' }]" /> <Verify @success="handleAlert('success')" @error="handleAlert('error')" :type="2" :showButton="false" fontSize="18px" ref="theVerify" ></Verify> <p class="now" @click="handleToggle()"> {{ flag ? `立即注册` : `已有登录帐号` }} </p> <div style="margin: 16px"> <van-button round block type="info" native-type="submit"> {{ flag ? `登录` : `注册` }} </van-button> </div> </van-form> </div> </template> <script> import Verify from "vue2-verify"; import { Notify } from "vant"; export default { components: { Verify, }, data() { return { username: "", password: "", flag: true, verifyFlag: false, }; }, methods: { onSubmit() { // console.log(`this.$refs['theVerify']-->`, this.$refs.theVerify); // checkCode() 验证; refresh() 重置; this.$refs.theVerify.checkCode(); // this.$refs['theVerify'].refresh()//重置 //验证码不通过 if (!this.verifyFlag) { Notify("验证码出错,请重试"); this.$refs.theVerify.refresh(); return; } // 注册 if (!this.flag) { console.log("进行注册"); this.$api .register(this.username, this.password) .then((value) => { // {"resultCode":200,"message":"SUCCESS","data":null} let { resultCode, message } = value; // console.log(resultCode, message, data); if (resultCode !== 200) { Notify(message || "注册出错,请重试"); this.$refs.theVerify.refresh(); return; } this.username = this.password = ``; Notify({ type: "success", message: "注册成功" }); this.$refs.theVerify.refresh(); this.flag = true; }) .catch((error) => { console.log(`error-->`, error); }); return; } this.$api .login(this.username, this.password) .then((value) => { // {"resultCode":200,"message":"SUCCESS","data":"a98cd1e0376b20776dcfb6ff8306031e"} console.log(value); let { resultCode, message, data } = value; if (resultCode !== 200) { Notify(message || "登录出错,请重试"); this.$refs.theVerify.refresh(); return; } this.username = this.password = ``; Notify({ type: "success", message: "登录成功" }); if (data) { localStorage.setItem("xfAppToken", data); } this.$router.push("/IndexView"); }) .catch((error) => { console.log(`error-->`, error); }) .finally(() => { console.log("登录操作后执行"); this.$refs.theVerify.refresh(); }); //登录 // console.log("进行登录"); }, handleAlert(text) { console.log("handleAlert", text); this.verifyFlag = text === "success" ? true : false; }, handleToggle() { this.flag = !this.flag; }, }, }; </script> <style lang="less"> .login-wrap { .van-nav-bar .van-icon { color: black; } .img-box { height: 160px; display: flex; justify-content: center; align-items: center; img { } } .van-button--info { background-color: #1baeae; border: 1px solid #1baeae; } .now { font-size: 14px; color: #1995fb; margin-left: 15px; } .cerify-code-panel { margin-top: 20px; margin-left: 15px; display: flex; .verify-code { width: 130px !important; height: 42px !important; line-height: 42px !important; } .verify-code-area { display: flex; .varify-input-code { height: 40px; line-height: 40px; width: 100px; margin-left: 10px; border: 1px solid #eee; font-size: 16px; text-indent: 10px; } .verify-change-code { font-size: 14px; } } } } </style>
-
-
在二次封装axios的
/src/http/http.js
中设置请求拦截器的处理。文章来源:https://www.toymoban.com/news/detail-429490.html -
在二次封装axios的
/src/http/http.js
中设置请求拦截器的处理。 -
在其它组件的接口随意发起一个axios请求,就会发现请求头上已经有了对应的token。文章来源地址https://www.toymoban.com/news/detail-429490.html
-
进阶参考
- 你不知道的Web Components现状 – 2022年对Web Components框架的解释
到了这里,关于20230428----重返学习-vue项目的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!