Vue2.0登录界面实战:从零到一构建企业级认证模块

张开发
2026/4/18 6:57:17 15 分钟阅读

分享文章

Vue2.0登录界面实战:从零到一构建企业级认证模块
1. 项目初始化与环境搭建第一次用Vue2.0做企业级登录模块时我踩过不少坑。记得当时为了赶进度直接复制了网上的代码结果项目结构一团乱麻后期维护差点崩溃。现在我会严格按照工程化标准来初始化项目这对后续开发效率影响巨大。先确保你的开发环境已经安装了Node.js建议12.x以上版本和npm。打开终端运行node -v检查版本如果还没安装去官网下载LTS版本就行。我习惯用yarn替代npm安装命令是npm install -g yarn。创建项目时别急着用vue create先想清楚项目名称和位置。我推荐这样操作vue create admin-login-system选择Manually select features勾选Babel、Router、Vuex、CSS Pre-processors和Linter。这里有个细节要注意问是否使用history模式时选no因为企业项目通常需要兼容老浏览器。安装基础依赖时最容易漏掉less-loader这个坑我踩过三次yarn add axios element-ui less less-loader5.0.0 -S注意less-loader的版本最新版可能不兼容Vue2.0这里固定用5.0.0版本最稳妥。安装完成后建议立即在package.json里固定版本号防止后续安装其他依赖时自动升级导致报错。2. 工程化配置实战2.1 路由配置技巧很多教程教的路由配置方式在实际项目中根本没法用。我总结了一套企业级路由配置方案首先在src下创建router/index.js但别急着写路由规则。先做好路由分层import Vue from vue import Router from vue-router import Login from /views/login/index.vue Vue.use(Router) // 防止连续点击多次路由报错 const originalPush Router.prototype.push Router.prototype.push function push(location) { return originalPush.call(this, location).catch(err err) } const router new Router({ mode: hash, base: process.env.BASE_URL, routes: [ { path: /, redirect: /login }, { path: /login, component: Login, meta: { title: 登录 } } ] }) // 动态修改页面标题 router.beforeEach((to, from, next) { document.title to.meta.title || 后台管理系统 next() }) export default router这种配置有三个优势1) 处理了路由重复跳转报错问题2) 支持动态标题3) 为后续权限控制预留了meta字段。记得在main.js里挂载路由时要用变量名router这是Vue的约定俗成。2.2 请求拦截器封装企业项目最怕的就是接口管理混乱。我建议在src下创建utils/request.jsimport axios from axios import { Message } from element-ui // 创建axios实例 const service axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 10000 }) // 请求拦截器 service.interceptors.request.use( config { config.headers[Authorization] sessionStorage.getItem(token) || return config }, error { console.log(error) return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response { const res response.data if (res.code ! 200) { Message({ message: res.message || Error, type: error, duration: 5 * 1000 }) return Promise.reject(new Error(res.message || Error)) } else { return res } }, error { Message({ message: error.message, type: error, duration: 5 * 1000 }) return Promise.reject(error) } ) export default service这种封装方式实现了1) 统一错误处理2) 自动携带token3) 响应数据预处理。记得在.env文件中配置VUE_APP_BASE_API环境变量不同环境可以设置不同接口地址。3. 登录界面开发实战3.1 表单组件设计用Element UI的表单组件时我强烈建议不要直接复制官网示例。企业项目需要更严谨的表单验证el-form refloginForm :modelloginForm :rulesloginRules classlogin-form auto-completeon label-positionleft el-form-item propusername el-input refusername v-modelloginForm.username placeholder请输入工号 nameusername typetext tabindex1 auto-completeon i slotprefix classel-icon-user / /el-input /el-form-item el-form-item proppassword el-input :keypasswordType refpassword v-modelloginForm.password :typepasswordType placeholder请输入密码 namepassword tabindex2 auto-completeon keyup.enter.nativehandleLogin i slotprefix classel-icon-lock / i slotsuffix classel-icon-view clickshowPwd / /el-input /el-form-item el-button :loadingloading typeprimary stylewidth:100%;margin-bottom:30px; click.native.preventhandleLogin 登录 /el-button /el-form对应的验证规则要这样写才够专业loginRules: { username: [ { required: true, trigger: blur, message: 请输入用户名 }, { pattern: /^[a-zA-Z0-9_-]{4,16}$/, message: 用户名必须是4-16位字母数字组合, trigger: blur } ], password: [ { required: true, trigger: blur, message: 请输入密码 }, { validator: (rule, value, callback) { if (value.length 6) { callback(new Error(密码不能少于6位)) } else if (!/[A-Z]/.test(value)) { callback(new Error(必须包含大写字母)) } else { callback() } }, trigger: blur } ] }3.2 登录逻辑实现登录按钮的点击事件要处理好几种边界情况async handleLogin() { try { this.loading true await this.$refs.loginForm.validate() const params { username: this.loginForm.username.trim(), password: this.loginForm.password } const res await loginApi(params) if (res.code 200) { sessionStorage.setItem(token, res.data.token) this.$router.push({ path: / }) } else { this.$message.error(res.message) } } catch (error) { console.error(error) } finally { this.loading false } }这里有几个关键点1) 表单验证通过才发起请求2) 用户名要去除首尾空格3) 无论成功失败都要关闭loading4) 错误要用统一的消息组件提示。4. 安全加固与性能优化4.1 路由守卫配置基础的路由守卫远远不够企业级项目需要更完善的认证检查router.beforeEach((to, from, next) { const hasToken sessionStorage.getItem(token) if (to.path /login) { if (hasToken) { next({ path: / }) } else { next() } } else { if (hasToken) { next() } else { next(/login?redirect${to.path}) } } })这种配置实现了1) 已登录用户访问登录页自动跳转首页2) 未登录用户访问其他页面重定向到登录页3) 记录目标路由便于登录后跳转。4.2 接口安全处理真实项目中我还会做这些安全加固密码加密传输import JSEncrypt from jsencrypt const encryptor new JSEncrypt() encryptor.setPublicKey(publicKey) const encrypted encryptor.encrypt(password)请求限流处理// request.js const pendingMap new Map() const addPending (config) { const key ${config.url}${config.method} if (pendingMap.has(key)) { config.cancelToken new axios.CancelToken(cancel { cancel(重复请求: ${key}) }) } else { pendingMap.set(key, config) } } const removePending (config) { const key ${config.url}${config.method} pendingMap.delete(key) }Token刷新机制// 响应拦截器中处理token过期 if (res.code 401) { const { data } await refreshToken() sessionStorage.setItem(token, data.token) return service.request(config) }这些措施能有效防止重放攻击、暴力破解等安全问题。实际项目中我还会配合后端做IP限制、验证码校验等更多防护。

更多文章