位置: IT常识 - 正文

基于Vue3和element-plus实现一个完整的登录功能(vue结合elementui)

发布时间:2024-01-14
基于Vue3和element-plus实现一个完整的登录功能

推荐整理分享基于Vue3和element-plus实现一个完整的登录功能(vue结合elementui),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:基于vue3和.net6,vue3.0 element,基于vue3和.net6,vue3.0和elementui,vue结合elementui,基于vue3和.net6,基于vue3和.net6,基于vue3和vite的表单设计器,内容如对您有帮助,希望把文章链接给更多的朋友!

先看一下最终要实现的效果:

登录页面:

注册页面:

(1)引入element-plus组件库

引入组件库的方式有好多种,在这里我就在main.js全局引入了.

npm i element-plus -S

main.js中代码:

import { createApp } from "vue";//element-plusimport ElementPlus from "element-plus";import "element-plus/dist/index.css";import App from "./App.vue";import router from "./router";import axios from "axios";import store from "./store";//创建实例const app = createApp(App);//全局应用配置app.config.globalProperties.$axios = axios;app.use(ElementPlus).use(store).use(router).mount("#app");

引入之后自己可以用几个按钮测试一下是否引入成功.

(2)登录及注册页面

html部分

views/account/Login.vue

<template><div id="login"><div class="form-wrap"><ul class="menu-tab"><li@click="data.current_menu = item.type":class="{ current: data.current_menu === item.type }"v-for="item in data.tab_menu":key="item.type">{{ item.label }}</li></ul><el-form ref="account_form" :model="data.form" :rules="data.form_rules"><el-form-item prop="username"><label class="form-label">用户名</label><el-input v-model="data.form.username"></el-input></el-form-item><el-form-item prop="password"><label class="form-label">密码</label><el-input type="password" v-model="data.form.password"></el-input></el-form-item><el-form-item prop="passwords" v-if="data.current_menu === 'register'"><label class="form-label">确认密码</label><el-input type="password" v-model="data.form.passwords"></el-input></el-form-item><el-form-item prop="code"><label class="form-label">验证码</label><el-row :gutter="10"><el-col :span="14"><el-input v-model="data.form.code"></el-input></el-col><el-col :span="10"><el-buttontype="success"class="el-button-block":loading="data.code_button_loading":disabled="data.code_button_disabled"@click="handlerGetCode">{{ data.code_button_text }}</el-button></el-col></el-row></el-form-item><el-form-item><el-buttontype="danger"@click="submitForm":disabled="data.submit_button_disabled":loading="data.submit_button_loading"class="el-button-block">{{ data.current_menu === "login" ? "登录" : "注册" }}</el-button></el-form-item></el-form></div></div></template><script>import { reactive, ref, onBeforeUnmount, getCurrentInstance } from "vue";import { useStore } from "vuex";import { useRouter } from "vue-router";// 校验类import {validate_email,validate_password,validate_code,} from "../../utils/validate";// sha1import sha1 from "js-sha1";// APIimport { GetCode } from "../../api/common";import { Register } from "../../api/account";// Loginexport default {name: "Login",components: {},props: {},setup() {// const instance = getCurrentInstance();// 获取实例上下文const { proxy } = getCurrentInstance();// storeconst store = useStore();// routerconst rotuer = useRouter();// 用户名校验const validate_name_rules = (rule, value, callback) => {let regEmail = validate_email(value);if (value === "") {callback(new Error("请输入邮箱"));} else if (!regEmail) {callback(new Error("邮箱格式不正确"));} else {callback();}};const validate_password_rules = (rule, value, callback) => {let regPassword = validate_password(value);// 获取“确认密码”// const passwordsValue = data.form.passwords;if (value === "") {callback(new Error("请输入密码"));} else if (!regPassword) {callback(new Error("请输入>=6并且<=20位的密码,包含数字、字母"));} else {callback();}};// 校验确认密码const validate_passwords_rules = (rule, value, callback) => {// 如果是登录,不需要校验确认密码,默认通过if (data.current_menu === "login") {callback();}let regPassword = validate_password(value);// 获取“密码”const passwordValue = data.form.password;if (value === "") {callback(new Error("请输入密码"));} else if (!regPassword) {callback(new Error("请输入>=6并且<=20位的密码,包含数字、字母"));} else if (passwordValue && passwordValue !== value) {callback(new Error("两次密码不一致"));} else {callback();}};const validate_code_rules = (rule, value, callback) => {let regCode = validate_code(value);if (value === "") {callback(new Error("请输入验证码"));} else if (!regCode) {callback(new Error("请输入6位的验证码"));} else {callback();}};const data = reactive({form: {username: "", // 用户名password: "", // 密码passwords: "", // 确认密码code: "", // 验证码},form_rules: {username: [{ validator: validate_name_rules, trigger: "change" }],password: [{ validator: validate_password_rules, trigger: "change" }],passwords: [{ validator: validate_passwords_rules, trigger: "change" }],code: [{ validator: validate_code_rules, trigger: "change" }],},tab_menu: [{ type: "login", label: "登录" },{ type: "register", label: "注册" },],current_menu: "login",/*** 获取验证码按钮交互*/code_button_disabled: false,code_button_loading: false,code_button_text: "获取验证码",code_button_timer: null,// 提交按钮submit_button_disabled: true,loading: false,});// 获取验证码const handlerGetCode = () => {const username = data.form.username;const password = data.form.password;const passwords = data.form.passwords;// 校验用户名if (!validate_email(username)) {proxy.$message.error({message: "用户名不能为空 或 格式不正确",type: "error",});return false;}// 校验密码if (!validate_password(password)) {proxy.$message({message: "密码不能为空 或 格式不正确",type: "error",});return false;}// 判断非 登录 时,校验两次密码if (data.current_menu === "register" && password !== passwords) {proxy.$message({message: "两次密码不一致",type: "error",});return false;}// 获取验证码接口const requestData = {username: data.form.username,module: data.current_menu,};data.code_button_loading = true;data.code_button_text = "发送中";GetCode(requestData).then((response) => {const resData = response;// 激活提交按钮data.submit_button_disabled = false;// 用户名存在if (resData.resCode === 1024) {proxy.$message.error(resData.message);return false;}// 成功 Elementui 提示proxy.$message({message: resData.message,type: "success",});// 执行倒计时countdown();}).catch(() => {data.code_button_loading = false;data.code_button_text = "获取验证码";});};/** 倒计时 */const countdown = (time) => {if (time && typeof time !== "number") {return false;}let second = time || 60; // 默认时间data.code_button_loading = false; // 取消加载data.code_button_disabled = true; // 禁用按钮data.code_button_text = `倒计进${second}秒`; // 按钮文本// 判断是否存在定时器,存在则先清除if (data.code_button_timer) {clearInterval(data.code_button_timer);}// 开启定时器data.code_button_timer = setInterval(() => {second--;data.code_button_text = `倒计进${second}秒`; // 按钮文本if (second <= 0) {data.code_button_text = `重新获取`; // 按钮文本data.code_button_disabled = false; // 启用按钮clearInterval(data.code_button_timer); // 清除倒计时}}, 1000);};/** 表单提交 */const account_form = ref(null);// formNameconst submitForm = () => {account_form.value.validate((valid) => {if (valid) {data.current_menu === "login" ? login() : register();} else {alert("表单验证不通过");return false;}});};/** 注册 */const register = () => {const requestData = {username: data.form.username,password: sha1(data.form.password),code: data.form.code,create: 1,};data.submit_button_loading = true;Register(requestData).then((response) => {proxy.$message({message: response.message,type: "success",});reset();}).catch(() => {data.submit_button_loading = false;});};/** 登录 */const login = () => {const requestData = {username: data.form.username,password: sha1(data.form.password),code: data.form.code,};data.submit_button_loading = true;store.dispatch("app/loginAction", requestData).then((response) => {data.submit_button_loading = false;proxy.$message({message: response.message,type: "success",});//路由跳转rotuer.push({ path: "/console" });reset();}).catch(() => {data.submit_button_loading = false;console.log("失败");});};/** 重置 */const reset = () => {// 重置表单proxy.$refs.form.resetFields();// 切回登录模式data.current_menu = "login";// 清除定时器data.code_button_timer && clearInterval(data.code_button_timer);// 获取验证码重置文本data.code_button_text = "获取验证码";// 获取验证码激活data.code_button_disabled = false;// 禁用提交按钮data.submit_button_disabled = true;// 取消提交按钮加载data.submit_button_loading = false;};// 组件销毁之前 - 生命周期onBeforeUnmount(() => {clearInterval(data.code_button_timer); // 清除倒计时});return {data,handlerGetCode,submitForm,account_form,};},};</script><style lang="scss" scoped>#login {height: 100vh; // 设置高度,居于浏览器可视区高度background-color: #344a5f; // 设置背景颜色}.form-wrap {width: 320px;padding-top: 100px; //上内边距margin: auto; // 块元素水平居中}.menu-tab {text-align: center;li {display: inline-block;padding: 10px 24px;margin: 0 10px;color: #fff;font-size: 14px;border-radius: 5px;cursor: pointer;&.current {background-color: rgba(0, 0, 0, 0.1);}}}.form-label {display: block; // 转为块元素color: #fff; // 设置字体颜色font-size: 14px; // 设置字体大小}</style>

js部分

<script>import { reactive, ref, getCurrentInstance, onBeforeUnmount } from "vue";import {validate_email,validate_password,validate_code,} from "@/utils/validate";import { GetCode } from "@/api/common";import { Register, Login } from "@/api/account";import sha1 from "js-sha1"; //密码加密// ErrorHttpexport default {setup() {const instance = getCurrentInstance();const { proxy } = getCurrentInstance();console.log("instance", instance);// console.log("proxy", proxy);// 用户名校验const validate_name_rules = (rule, value, callback) => {let regEmail = validate_email(value);if (value === "") {callback(new Error("请输入邮箱"));} else if (!regEmail) {callback(new Error("邮箱格式不正确"));} else {callback();}};//获取验证码const handleGetCode = () => {const username = data.form.username;const password = data.form.password;const passwords = data.form.passwords;//校验用户名if (!validate_email(username)) {proxy.$message({message: "用户名不能为空 或 格式不正确",type: "error",});return false;}//校验密码if (!validate_password(password)) {proxy.$message({message: "密码不能为空 或 格式不正确",type: "error",});return false;}//判断为注册时,校验两次密码if (data.current_menu === "redister" ** (password !== passwords)) {proxy.$message({message: "两次密码不一致",type: "error",});return false;}//获取验证码接口const requestData = {username: data.form.username,module: "register",};data.code_button_loading = true;data.code_button_text = "发送中";GetCode(requestData).then((res) => {// console.log("123", res.data);验证码// const data=res.resCodeconst data = res;if (data.resCode === 1024) {proxy.$message.error(data.message);return false;}// 成功 Elementui 提示proxy.$message({message: data.message,type: "success",});//执行倒计时countdown();}).catch((err) => {console.log(err);data.code_button_loading = false;data.code_button_text = "发送验证码";});// ErrorHttp(requestData)// .then((res) => {// console.log(res.data);// // const data=res.resCode// const data = res.data;// if (data.resCode === 1024) {// proxy.$message.error(data.message);// return false;// }// // 成功 Elementui 提示// proxy.$message({// message: data.message,// type: "success",// });// //执行倒计时// countdown();// })// .catch((err) => {// console.log(err);// data.code_button_loading = false;// data.code_button_text = "发送验证码";// });};/** 倒计时 */const countdown = (time) => {if (time && typeof time !== "number") {return false;}let second = time || 60; // 默认时间data.code_button_loading = false; // 取消加载data.code_button_disabled = true; // 禁用按钮data.code_button_text = `倒计进${second}秒`; // 按钮文本// 判断是否存在定时器,存在则先清除if (data.code_button_timer) {clearInterval(data.code_button_timer);}// 开启定时器data.code_button_timer = setInterval(() => {second--;data.code_button_text = `倒计进${second}秒`; // 按钮文本if (second <= 0) {data.code_button_text = `重新获取`; // 按钮文本data.code_button_disabled = false; // 启用按钮clearInterval(data.code_button_timer); // 清除倒计时}}, 1000);};// 组件销毁之前 - 生命周期onBeforeUnmount(() => {clearInterval(data.code_button_timer); // 清除倒计时});// 校验确认密码const validate_password_rules = (rule, value, callback) => {let regPassword = validate_password(value);if (value === "") {callback(new Error("请输入密码"));} else if (!regPassword) {callback(new Error("请输入>=6并且<=20位的密码,包含数字、字母"));} else {callback();}};// 校验确认密码const validate_passwords_rules = (rule, value, callback) => {// 如果是登录,不需要校验确认密码,默认通过if (data.current_menu === "login") {callback();}let regPassword = validate_password(value);// 获取“密码”const passwordValue = data.form.password;if (value === "") {callback(new Error("请输入密码"));} else if (!regPassword) {callback(new Error("请输入>=6并且<=20位的密码,包含数字、字母"));} else if (passwordValue && passwordValue !== value) {callback(new Error("两次密码不一致"));} else {callback();}};const validate_code_rules = (rule, value, callback) => {let regCode = validate_code(value);// 激活提交按钮data.submit_button_disabled = false;if (value === "") {callback(new Error("请输入验证码"));} else if (!regCode) {callback(new Error("请输入6位的验证码"));} else {callback();}};// 提交表单const submitForm = () => {// let res = proxy.$refs.account_form;proxy.$refs.account_form.validate((valid) => {if (valid) {console.log("提交表单", current_menu.value);current_menu.value === "login" ? login() : register();// register();} else {alert("error submit!");return false;}});// console.log(" 提交表单", res);};/** 登录 */const login = () => {const requestData = {username: data.form.username,password: sha1(data.form.password),code: data.form.code,};data.submit_button_loading = true;Login(requestData).then((response) => {console.log("login", response);data.submit_button_loading = false;proxy.$message({message: response.message,type: "success",});reset();}).catch((error) => {console.log("登录失败", error);data.submit_button_loading = false;});};//注册const register = () => {const requestData = {username: data.form.username,password: sha1(data.form.password),code: data.form.code,};data.submit_button_loading = true;Register(requestData).then((res) => {proxy.$message({message: res.message,type: "success",});}).catch((error) => {console.log("注册错误", error);data.submit_button_loading = false;});};/** 重置 */const reset = () => {// 重置表单proxy.$refs.form.resetFields();// 切回登录模式data.current_menu = "login";// 清除定时器data.code_button_timer && clearInterval(data.code_button_timer);// 获取验证码重置文本data.code_button_text = "获取验证码";// 获取验证码激活data.code_button_disabled = false;// 禁用提交按钮data.submit_button_disabled = true;// 取消提交按钮加载data.submit_button_loading = false;};const data = reactive({form_rules: {username: [{ validator: validate_name_rules, trigger: "change" }],password: [{ validator: validate_password_rules, trigger: "change" }],passwords: [{ validator: validate_passwords_rules, trigger: "change" }],code: [{ validator: validate_code_rules, trigger: "change" }],},form: {username: "", // 用户名password: "", // 密码passwords: "", // 确认密码code: "", // 验证码},tab_menu: [{ type: "login", label: "登录" },{ type: "register", label: "注册" },],/*** 获取验证码按钮交互*/code_button_disabled: false,code_button_loading: false,code_button_text: "获取验证码",code_button_timer: null,// 提交按钮submit_button_disabled: true,});const toggleMenu = (type) => {current_menu.value = type;};let current_menu = ref(data.tab_menu[0].type);// const dataItem = toRefs(data);return {// ...dataItem,data,current_menu,toggleMenu,handleGetCode,submitForm,register,reset,login,};},};</script>

css部分(使用了scss)

<style lang="scss" scoped>#login {height: 100vh;background-color: #344a5f;}.form-wrap {width: 320px;padding-top: 100px;margin: auto;}.menu-tab {text-align: center;li {display: inline-block;padding: 10px 24px;margin: 0 10px;color: #fff;font-size: 14px;border-radius: 5px;cursor: pointer;&.current {background-color: rgba(0, 0, 0, 0.1);}}}.form-label {display: block;color: #fff;font-size: 14px;}</style>

(3)封装一些公共方法及样式

新建styles文件夹,然后新建几个样式文件:

normalize.scss

/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css *//* Document========================================================================== *//*** 1. Correct the line height in all browsers.* 2. Prevent adjustments of font size after orientation changes in iOS.*//* div的默认样式不存在padding和margin为0的情况*/html, body, span, applet, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,a, abbr, acronym, address, big, cite, code,del, dfn, em, img, ins, kbd, q, s, samp,small, strike, strong, sub, sup, tt, var,b, u, i, center,dl, dt, dd, ol, ul,fieldset, form, legend,table, caption, tbody, tfoot, thead, tr, th, td,article, aside, canvas, details, embed,figure, figcaption, footer, header, hgroup,menu, nav, output, ruby, section, summary,time, mark, audio, video {margin: 0;padding: 0;font-size: 100%;font: inherit;vertical-align: baseline;}/* HTML5 display-role reset for older browsers */article, aside, details, figcaption, figure,footer, header, hgroup, menu, nav, section {display: block;}html {line-height: 1.15; /* 1 */-webkit-text-size-adjust: 100%; /* 2 */}/* Sections========================================================================== *//*** Remove the margin in all browsers.*/body {margin: 0;font-family: 'Microsoft YaHei';font-size: 14px;}/*** Render the `main` element consistently in IE.*/main {display: block;}/*** Correct the font size and margin on `h1` elements within `section` and* `article` contexts in Chrome, Firefox, and Safari.*//* Grouping content========================================================================== *//*** 1. Add the correct box sizing in Firefox.* 2. Show the overflow in Edge and IE.*/hr {box-sizing: content-box; /* 1 */height: 0; /* 1 */overflow: visible; /* 2 */}/*** 1. Correct the inheritance and scaling of font size in all browsers.* 2. Correct the odd `em` font sizing in all browsers.*/pre {font-family: monospace, monospace; /* 1 */font-size: 1em; /* 2 */}/* Text-level semantics========================================================================== *//*** Remove the gray background on active links in IE 10.*/a {background-color: transparent;text-decoration: none;}/*** 1. Remove the bottom border in Chrome 57-* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.*/abbr[title] {border-bottom: none; /* 1 */text-decoration: underline; /* 2 */text-decoration: underline dotted; /* 2 */}/*** Add the correct font weight in Chrome, Edge, and Safari.*/b,strong {font-weight: bolder;}/*** 1. Correct the inheritance and scaling of font size in all browsers.* 2. Correct the odd `em` font sizing in all browsers.*/code,kbd,samp {font-family: monospace, monospace; /* 1 */font-size: 1em; /* 2 */}/*** Add the correct font size in all browsers.*/small {font-size: 80%;}/*** Prevent `sub` and `sup` elements from affecting the line height in* all browsers.*/sub,sup {font-size: 75%;line-height: 0;position: relative;vertical-align: baseline;}sub {bottom: -0.25em;}sup {top: -0.5em;}/* Embedded content========================================================================== *//*** Remove the border on images inside links in IE 10.*/img {display: block;border-style: none;}/* Forms========================================================================== *//*** 1. Change the font styles in all browsers.* 2. Remove the margin in Firefox and Safari.*/button,input,optgroup,select,textarea {font-family: inherit; /* 1 */font-size: 100%; /* 1 */margin: 0; /* 2 */}/*** Show the overflow in IE.* 1. Show the overflow in Edge.*/button,input { /* 1 */overflow: visible;}/*** Remove the inheritance of text transform in Edge, Firefox, and IE.* 1. Remove the inheritance of text transform in Firefox.*/button,select { /* 1 */text-transform: none;}/*** Correct the inability to style clickable types in iOS and Safari.*/button,[type="button"],[type="reset"],[type="submit"] {-webkit-appearance: button;}/*** Remove the inner border and padding in Firefox.*/button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner {border-style: none;padding: 0;}/*** Restore the focus styles unset by the previous rule.*/button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring {outline: 1px dotted ButtonText;}/*** Correct the padding in Firefox.*/fieldset {padding: 0.35em 0.75em 0.625em;}/*** 1. Correct the text wrapping in Edge and IE.* 2. Correct the color inheritance from `fieldset` elements in IE.* 3. Remove the padding so developers are not caught out when they zero out* `fieldset` elements in all browsers.*/legend {box-sizing: border-box; /* 1 */color: inherit; /* 2 */display: table; /* 1 */max-width: 100%; /* 1 */padding: 0; /* 3 */white-space: normal; /* 1 */}/*** Add the correct vertical alignment in Chrome, Firefox, and Opera.*/progress {vertical-align: baseline;}/*** Remove the default vertical scrollbar in IE 10+.*/textarea {overflow: auto;}/*** 1. Add the correct box sizing in IE 10.* 2. Remove the padding in IE 10.*/[type="checkbox"],[type="radio"] {box-sizing: border-box; /* 1 */padding: 0; /* 2 */}/*** Correct the cursor style of increment and decrement buttons in Chrome.*/[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button {height: auto;}/*** 1. Correct the odd appearance in Chrome and Safari.* 2. Correct the outline style in Safari.*/[type="search"] {-webkit-appearance: textfield; /* 1 */outline-offset: -2px; /* 2 */}/*** Remove the inner padding in Chrome and Safari on macOS.*/[type="search"]::-webkit-search-decoration {-webkit-appearance: none;}/*** 1. Correct the inability to style clickable types in iOS and Safari.* 2. Change font properties to `inherit` in Safari.*/::-webkit-file-upload-button {-webkit-appearance: button; /* 1 */font: inherit; /* 2 */}/* Interactive========================================================================== *//** Add the correct display in Edge, IE 10+, and Firefox.*/details {display: block;}/** Add the correct display in all browsers.*/summary {display: list-item;}/* Misc========================================================================== *//*** Add the correct display in IE 10+.*/template {display: none;}/*** Add the correct display in IE 10.*/[hidden] {display: none;}ul, li { list-style: none; }

elementui.scss(当时测试时用的)

.el-button-block{display: block;width: 100%;}

新建main.scss(引入上方两个样式文件)

@import "./normalize.scss";@import './elementui.scss'

vue.config.js配置一下样式文件

css: {// 是否使用css分离插件 ExtractTextPluginextract: true,// 开启 CSS source maps?sourceMap: false,// css预设器配置项loaderOptions: {scss: {additionalData: `@import "./src/styles/main.scss";`,},},// requireModuleExtension: true,},

登录中封装的校验方法

新建utils文件夹,

a.validate.js

// 校验邮箱export function validate_email(value) {let regEmail = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;return regEmail.test(value);}// 校验密码export function validate_password(value) {let regPassword = /^(?!\D+$)(?![^a-zA-Z]+$)\S{6,20}$/;return regPassword.test(value);}// 校验验证码export function validate_code(value) {let regCode = /^[a-z0-9]{6}$/;return regCode.test(value);}

封装请求方法

npm i axios -S

记得先在main.js中引入axios

import axios from "axios";

utils中新建request.js

import axios from "axios";//引入element-plusimport { ElMessage } from "element-plus";console.log("11", process.env.VUE_APP_API); //undefined??//创建实例const service = axios.create({baseURL: "/devApi", //请求地址timeout: 5000, //超时});//添加请求拦截器service.interceptors.request.use(function (config) {//在发送请求之前做些什么return config;},function (error) {console.log(error.request);const errorData = JSON.parse(error.request.response);if (errorData.message) {//判断是否具有message属性ElMessage({message: errorData.message,type: "error",});}//对请求错误做些什么return Promise.reject(errorData);});//添加响 应拦截器service.interceptors.response.use(function (response) {//对响应数据做些什么console.log("响应数据", response);const data = response.data;if (data.resCode === 0) {return Promise.resolve(data);} else {ElMessage({message: data.message,type: "error",});return Promise.reject(data);}},function (error) {//对响应错误做些什么const errorData = JSON.parse(error.request.response);if (errorData.message) {//判断是否具有message属性ElMessage({message: errorData.message,type: "error",});}return Promise.reject(errorData);});//暴露serviceexport default service;

(4)配置环境变量

基于Vue3和element-plus实现一个完整的登录功能(vue结合elementui)

和项目根路径同级,新建几个文件:

.env.development

VUE_APP_API = '/devApi'

可以自定义,但是必须是VUE_APP_XXX的格式

.env.production

VUE_APP_API = '/production'

.env.test

VUE_APP_API = '/test'

配置完后记得在axios文件中打印一下,看下能输出自己配置的环境变量吗.

(5)配置代理(跨域)

基本大同小异,代理地址改成自己的就可以了.

devServer: {open: false, //编译完成是否自动打开网页host: "0.0.0.0", //指定使用地址,默认是localhost,0.0.0.0代表可以被外界访问port: 8080,proxy: {"/devApi": {target: "http://v3.web-jshtml.cn/api", //(必选)API服务器的地址changeOrigin: true, //(必选) 是否允许跨域ws: false, //(可选) 是否启用websocketssecure: false, //(可选) 是否启用https接口pathRewrite: {"^/devApi": "", //匹配开头为/devApi的字符串,并替换成空字符串},},},},

登录基本上是完成了,还有优化的点,比如说登录放在vuex中,

继续改造一下,把登录放在vuex中实现:

先看一下vuex的执行逻辑图:

store新建modules文件夹,新建app.js:

import { Login } from "@/api/account";const state = {count: 100,};const getters = {};const mutations = {};const actions = {loginAction(context, requestData) {return new Promise((resolve, reject) => {Login(requestData).then((response) => {resolve(response);}).catch((error) => {reject(error);});});},};export default {namespaced: true,state,getters,mutations,actions,};

登录页面改造:

import { useStore } from "vuex"; // storeconst store = useStore();

注释掉之前的代码:

/** 登录 */// const login = () => {// const requestData = {// username: data.form.username,// password: sha1(data.form.password),// code: data.form.code,// };// data.submit_button_loading = true;// Login(requestData)// .then((response) => {// console.log("login", response);// data.submit_button_loading = false;// proxy.$message({// message: response.message,// type: "success",// });// reset();// })// .catch((error) => {// console.log("登录失败", error);// data.submit_button_loading = false;// });// };const login = () => {const requestData = {username: data.form.username,password: sha1(data.form.password),code: data.form.code,};data.submit_button_loading = true;store.dispatch("app/loginAction", requestData).then((response) => {proxy.$message({message: response.message,type: "success",});reset();}).catch((error) => {console.log("失败", error);});};

好了,等有继续优化的地方我再继续完善.

(4)路由守卫

先来看一下总体的思路图:

在router文件下新建permit.js:

import router from "./index";//cookieimport { getToken } from "@/utils/cookies";//全局路由守卫router.beforeEach((to, from) => {// console.log("from", from);//token不存在if (!getToken()) {console.log("to", to);if (to.name !== "Login") {return {name: "Login",};}}});//全局后置守卫router.afterEach((to, from) => {console.log(to);console.log(from);});

引入到main.js中:

//路由守卫import "./router/permit";

utils文件中新建cookies.js文件

先安装js-cookie:

npm i js-cookie -S

cookies.js:

import Cookies from "js-cookie";//变量const tokenKey = "tokenAdmin";const usernameKey = "username";//获取tokenexport function getToken() {return Cookies.get(tokenKey);}//写入tokenexport function setToken(value) {return Cookies.set(tokenKey, value);}//删除tokenexport function removeToken() {return Cookies.remove(tokenKey);}//写入 usernameexport function setUsername(value) {return Cookies.set(usernameKey, value);}//获取 usernameexport function getUsername() {return Cookies.get(usernameKey);}//删除 usernameexport function removeUsername() {return Cookies.remove(usernameKey);}

vuex中改造一下:

store/app.js

import { Login, Logout } from "@a/account";import {setToken,setUsername,getToken,getUsername,removeToken,removeUsername,} from "@u/cookies";const state = {token: "" || getToken(),username: "" || getUsername(),collapse: JSON.parse(sessionStorage.getItem("collapse")) || false,};const getters = {};const mutations = {SET_COLLAPSE(state) {state.collapse = !state.collapse;sessionStorage.setItem("collapse", JSON.stringify(state.collapse));},//设置tokenSET_TOKEN(state, value) {state.token = value;value && setToken(value); //当value存在时写入token},//设置用户名SET_USERNAME(state, value) {state.username = value;value && setUsername(value); //当value存在时写入token},};const actions = {//登录loginAction(context, requestData) {return new Promise((resolve, reject) => {Login(requestData).then((response) => {let data = response.data;context.commit(" SET_TOKEN", data.token);context.commit(" SET_USERNAME", data.username);resolve(response);}).catch((error) => {reject(error);});});},//退出logoutAction({ commit }) {return new Promise((resolve, reject) => {Logout().then((response) => {removeToken();removeUsername();commit(" SET_TOKEN", "");commit(" SET_USERNAME", "");resolve(response);}).catch((error) => {reject(error);});});},};export default {namespaced: true,state,getters,mutations,actions,};

主页有退出的话可以这么来触发:

<span class="logout" @click="handleLogout"><svg-icon iconName="logout" className="icon-logout"></svg-icon></span> //退出const handleLogout = () => {proxy.$confirm("确定退出管理后台", "提示", {confirmButtonText: "确定",cancelButtonText: "取消",type: "warning",}).then(() => {store.dispatch("app/logoutAction").then((res) => {proxy.$message({type: "success",message: res.message,});replace({name: "Login",});});}).catch(() => {// catch error});};

记得引入和返回,不能忘记:

import { useStore } from "vuex";import { ref, getCurrentInstance } from "vue";import { useRouter } from "vue-router"; //获取实例上下文const { proxy } = getCurrentInstance();//引入routerconst { replace } = useRouter();const store = useStore(); return {handleLogout,};

再来改造一下之前封装的axios方法:

import axios from "axios";//引入element-plusimport { ElMessage } from "element-plus";// console.log("11", process.env.VUE_APP_API); //undefined??//cookies+import { getToken, getUsername, removeToken, removeUsername } from "./cookies";//引入路由+import router from "@/router";//创建实例const service = axios.create({baseURL: "/devApi", //请求地址timeout: 5000, //超时});//添加请求拦截器service.interceptors.request.use(function (config) {//在发送请求之前做些什么+ if (getToken()) {config.headers["Token"] = getToken(); //携带token Token可以和后端约定}+ if (getUsername()) {config.headers["Username"] = getUsername();//Username可以和后端约定}console.log("config", config);return config;},function (error) {console.log(error.request);const errorData = JSON.parse(error.request.response);if (errorData.message) {//判断是否具有message属性ElMessage({message: errorData.message,type: "error",});}//对请求错误做些什么return Promise.reject(errorData);});//添加响 应拦截器service.interceptors.response.use(function (response) {//对响应数据做些什么console.log("响应数据", response);const data = response.data;+ if (data.resCode === 0) {return Promise.resolve(data);} else {ElMessage({message: data.message,type: "error",});return Promise.reject(data);}},function (error) {//对响应错误做些什么const errorData = JSON.parse(error.request.response);if (errorData.message) {//判断是否具有message属性ElMessage({message: errorData.message,type: "error",});}//token失效自动退出+ if (errorData.resCode === 1010) {router.replace({name: "Login",});removeToken();removeUsername();}return Promise.reject(errorData);});//暴露serviceexport default service;

再来优化一下目录别名这块:

vue.config.js

configureWebpack: (config) => {config.resolve = {// 配置解析别名extensions: [".js", ".json", ".vue"], // 自动添加文件名后缀alias: {"@": path.resolve(__dirname, "./src"),"@u": path.resolve(__dirname, "./src/utils"),"@a": path.resolve(__dirname, "./src/api"),"@c": path.resolve(__dirname, "./src/components"),},};},

改完记得重启项目,所以之前的代码就这样写了:

import { Login, Logout } from "@a/account";import {setToken,setUsername,getToken,getUsername,removeToken,removeUsername,} from "@u/cookies";
本文链接地址:https://www.jiuchutong.com/zhishi/295375.html 转载请保留说明!

上一篇:【审稿意见】科研菜鸟如何攥写审稿意见?万能模板!!!(审稿意见范例)

下一篇:前端技术搭建井字游戏(内含源码)(前端cli搭建)

  • 荣耀50se微信视频可以美颜吗(荣耀50se微信视频聊天怎么设置美颜功能)

    荣耀50se微信视频可以美颜吗(荣耀50se微信视频聊天怎么设置美颜功能)

  • vivo手机怎么切换经典桌面(vivo手机怎么切换卡1卡2)

    vivo手机怎么切换经典桌面(vivo手机怎么切换卡1卡2)

  • excel表格筛选条件怎么设置(excel表格筛选条件区域)

    excel表格筛选条件怎么设置(excel表格筛选条件区域)

  • 手机本地无签名证书什么意思(手机本地无签名怎么回事)

    手机本地无签名证书什么意思(手机本地无签名怎么回事)

  • 谷歌框架有什么害处?(谷歌服务框架)

    谷歌框架有什么害处?(谷歌服务框架)

  • 输入其他ipad密码是什么情况(输入其他ipad密码怎么回事)

    输入其他ipad密码是什么情况(输入其他ipad密码怎么回事)

  • 什么是设备解绑(设备已解绑,请联系管理人员)

    什么是设备解绑(设备已解绑,请联系管理人员)

  • 为什么微信发的视频会抖(为什么微信发的图片会自动保存到相册)

    为什么微信发的视频会抖(为什么微信发的图片会自动保存到相册)

  • 手机屏幕闪绿屏能修吗(手机屏幕闪绿屏怎么办)

    手机屏幕闪绿屏能修吗(手机屏幕闪绿屏怎么办)

  • 淘宝评分红色和灰色有什么区别(淘宝评分红色和绿色有什么区别)

    淘宝评分红色和灰色有什么区别(淘宝评分红色和绿色有什么区别)

  • 手机没玩多久就发烫是怎么回事(手机没玩多久就特别烫是什么原因)

    手机没玩多久就发烫是怎么回事(手机没玩多久就特别烫是什么原因)

  • 网站进不去了怎么回事(网站进不去怎么弄)

    网站进不去了怎么回事(网站进不去怎么弄)

  • 快手缴纳保证金能退吗(快手缴纳保证金是什么意思)

    快手缴纳保证金能退吗(快手缴纳保证金是什么意思)

  • qq上的帆船是什么意思(qq里面的帆船什么意思)

    qq上的帆船是什么意思(qq里面的帆船什么意思)

  • 同一个手机微信卸载重装后记录还有吗(同一个手机微信分身怎么迁移到微信)

    同一个手机微信卸载重装后记录还有吗(同一个手机微信分身怎么迁移到微信)

  • 手机qq怎么开厘米秀(qq怎么开?)

    手机qq怎么开厘米秀(qq怎么开?)

  • 华为怎样取消健康使用手机(如何关闭华为健康)

    华为怎样取消健康使用手机(如何关闭华为健康)

  • iphonex黑屏转圈(iphonex黑屏转圈跳回锁屏)

    iphonex黑屏转圈(iphonex黑屏转圈跳回锁屏)

  • 怎样刷快手播放量(快手怎样用手机刷播放)

    怎样刷快手播放量(快手怎样用手机刷播放)

  • 小米手机私密空间怎么打开(小米手机私密空间文件恢复)

    小米手机私密空间怎么打开(小米手机私密空间文件恢复)

  • 惠普capslock建闪但不开机(惠普电脑capslock一直闪 电脑电源开不了机也关不了机)

    惠普capslock建闪但不开机(惠普电脑capslock一直闪 电脑电源开不了机也关不了机)

  • wlan和wifi的区别(wlan和wifi的区别ipad哪个好)

    wlan和wifi的区别(wlan和wifi的区别ipad哪个好)

  • 小米门禁卡模拟在哪(小米门禁卡模拟nfc)

    小米门禁卡模拟在哪(小米门禁卡模拟nfc)

  • 电脑4g和8g的区别(电脑4g内存和8g)

    电脑4g和8g的区别(电脑4g内存和8g)

  • gah95on6.exe是什么进程 作用是什么 gah95on6进程查询(gws.exe是啥)

    gah95on6.exe是什么进程 作用是什么 gah95on6进程查询(gws.exe是啥)

  • 企业所得税年报怎么查询
  • 中国电子口岸证书错误
  • 一般纳税人用金蝶新建账套用什么会计制度好
  • 政府补助具有无偿性的特征
  • 长期股权投资超过50%
  • 税局代开专票对方隔月退回重开如何做账务处理呢?
  • 超市顾客返利如何做账务处理?
  • 购买理财产品现金流量处理怎么做?
  • 产生的信息服务有哪些
  • 在建工程的计算公式
  • 滞留发票产生的原因主要包括哪些?
  • 广告设计制作的技术框架
  • 餐饮行业月营业额怎么算
  • 个税申报表怎么打印
  • 个人公寓出租给公司要交税吗?
  • 增值税是什么鬼
  • 非税收入的发票能抵扣吗
  • 外汇局网上申报
  • 专项应付款会计科目代码
  • 腾讯手游助手qq版本过低
  • ie增强的安全配置已启用上不了网
  • 电子发票如何作废冲红
  • 对公账户被诈骗转款728000会怎么样呢
  • linux环境什么意思
  • 进项税留抵期限
  • 预付款挂账什么意思
  • memcache php
  • 苹果a1586是什么配置
  • hp workwise service是什么
  • keyemain.exe是什么
  • 新事业单位会计准则
  • 瑞士·劳特布龙嫩小镇
  • vue控制按钮是否禁用
  • 项目的分包行为是否合理
  • 高新技术企业取消资格怎么处罚
  • 演员片酬要分给经纪公司吗
  • 一个残疾证一年单位免多少税2023
  • 成本费用做账
  • 购货方享受现金流量吗
  • 固定资产包括无形资产吗?
  • 行政事业单位支出劳务费规定
  • 移动平均法适用范围
  • 预收账款未发货会计分录
  • 公司食堂吃饭没钱怎么办
  • db management
  • mongodb bi
  • 织梦系统安装教程
  • 工程提成会计分录怎么做
  • 福利费用属于哪个部门
  • 以前年度损益调整结转到哪里
  • 没有增值税专用发票
  • 企业取得交易性金融资产的主要目的是
  • 成本发票未到怎么入账
  • 提前报废固定资产会导致账面价值减少吗
  • 机物料消耗计入什么费用
  • 车票抵扣填在申请表哪里
  • 来料加工费用价格表
  • 财务票子怎么粘
  • 旅游饮食服务业会计课后答案
  • xp安装声卡驱动
  • linux命令提示符不见了
  • bios中英文对照表图新版
  • debian glibc
  • 苹果电脑使用u盾怎么用
  • linux的收获
  • linux特殊权限命令
  • linux dhcpv6
  • linux在哪里操作
  • linux xfs 扩容
  • win7运行窗口在哪
  • 深入理解javascript特性.pdf
  • dos批命令
  • 为了防止编码过程的过载现象出现
  • js对象常用方法
  • unity3d spine
  • js修改地址栏参数但不让他跳转
  • shell脚本实现文件移动、复制等操作
  • 教育费附加最新政策2023
  • 电子税务局个体工商户如何登陆
  • 购买服务合同模版
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号