一、项目搭建与基础配置
环境准备
使用 Vue CLI 或 Vite 创建项目,推荐组合:Vue3 + Element Plus + Vue Routernpm create vue@latest npm install element-plus @element-plus/icons-vue vue-router
全局配置(main.js)
import { createApp } from 'vue' import ElementPlus from 'element-plus' import router from './router' import 'element-plus/dist/index.css' const app = createApp(App) app.use(ElementPlus) app.use(router) app.mount('#app')
二、登录页面核心实现
模板结构(login.vue)
<template> <div class="login-container"> <el-form ref="formRef" :model="form" :rules="rules"> <h2 class="title">校园交易平台</h2> <el-form-item prop="username"> <el-input v-model="form.username" prefix-icon="User" placeholder="请输入手机号" /> </el-form-item> <el-form-item prop="password"> <el-input v-model="form.password" prefix-icon="Lock" type="password" show-password placeholder="请输入密码" @keyup.enter="handleLogin" /> </el-form-item> <el-button type="primary" :loading="loading" @click="handleLogin" > 登录 </el-button> <div class="links"> <router-link to="/register">立即注册</router-link> <router-link to="/forgot">忘记密码?</router-link> </div> </el-form> </div> </template>
数据与验证逻辑
<script setup> import { ref, reactive } from 'vue' import { useRouter } from 'vue-router' import { ElMessage } from 'element-plus' const form = reactive({ username: '', password: '' }) const rules = reactive({ username: [ { required: true, message: '请输入手机号', trigger: 'blur' }, { pattern: /^1[3-9]\d{9}$/, message: '手机号格式错误' } ], password: [ { required: true, message: '请输入密码', trigger: 'blur' }, { min: 6, max: 16, message: '长度6-16位' } ] }) const loading = ref(false) const formRef = ref(null) const router = useRouter() const handleLogin = async () => { try { await formRef.value.validate() loading.value = true // 模拟API请求 await new Promise(resolve => setTimeout(resolve, 1000)) sessionStorage.setItem('token', 'demo_token') ElMessage.success('登录成功') router.replace('/dashboard') } catch (error) { console.error('登录失败:', error) } finally { loading.value = false } } </script>
样式优化要点
<style scoped> .login-container { height: 100vh; display: grid; place-items: center; background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); } .title { text-align: center; margin-bottom: 2rem; color: #2c3e50; font-size: 1.8rem; } :deep(.el-form) { width: 400px; padding: 2rem; background: rgba(255,255,255,0.95); border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.1); } .el-button { width: 100%; margin-top: 1rem; } .links { margin-top: 1.5rem; display: flex; justify-content: space-between; a { color: #409eff; text-decoration: none; transition: color 0.3s; &:hover { color: #66b1ff; } } } </style>
三、进阶功能实现
路由守卫配置
// router/index.js router.beforeEach((to) => { const isAuthenticated = sessionStorage.getItem('token') if (to.meta.requiresAuth && !isAuthenticated) { return '/login' } if (to.path === '/login' && isAuthenticated) { return '/dashboard' } })
安全增强方案
密码加密传输(使用crypto-js)
添加验证码功能
请求限流与防重放攻击
import CryptoJS from 'crypto-js' const encryptPassword = (password) => { return CryptoJS.SHA256(password).toString() }
第三方登录集成
<template> <div class="oauth-login"> <el-divider>第三方登录</el-divider> <div class="oauth-buttons"> <el-button @click="handleWechatLogin"> <svg-icon icon-class="wechat" /> 微信登录 </el-button> </div> </div> </template>
四、最佳实践与注意事项
表单验证优化
异步验证手机号是否注册
密码强度实时检测
const checkUsername = async (rule, value, callback) => { if (!value) return callback(new Error('请输入手机号')) if (!/^1[3-9]\d{9}$/.test(value)) return callback(new Error('格式错误')) try { const { data } = await api.checkUsername(value) if (!data.exist) callback(new Error('该用户未注册')) } catch (error) { callback(new Error('验证失败')) } }
用户体验优化
自动填充最近登录账号
记住密码功能(加密存储)
加载状态管理
// 自动填充 const lastUsername = localStorage.getItem('lastUsername') if (lastUsername) form.username = lastUsername // 记住密码 const savePassword = ref(false) watch(savePassword, (val) => { if (val) { localStorage.setItem('remembered', JSON.stringify(form)) } else { localStorage.removeItem('remembered') } })
错误处理规范
try { const res = await loginApi(formData) if (res.code === 1001) { ElMessage.warning('该账号已被冻结') } } catch (err) { ElMessage.error({ message: `登录失败: ${err.message}`, grouping: true // 相同错误合并显示 }) }
五、典型问题解决方案
跨域问题处理
// vite.config.js export default defineConfig({ server: { proxy: { '/api': { target: 'http://backend.example.com', changeOrigin: true, rewrite: (path) => path.replace(/^\/api/, '') } } } })
响应式布局适配
@media (max-width: 768px) { .login-container { padding: 1rem; :deep(.el-form) { width: 100%; margin: 0 1rem; } } }
浏览器兼容问题
使用@vitejs/plugin-legacy处理ES6+语法
添加autoprefixer自动补全CSS前缀