使用 Vue 开发登录页面的完整指南

发布于:2025-04-20 ⋅ 阅读:(9) ⋅ 点赞:(0)
一、项目搭建与基础配置
  1. 环境准备
    使用 Vue CLI 或 Vite 创建项目,推荐组合:Vue3 + Element Plus + Vue Router

    npm create vue@latest
    npm install element-plus @element-plus/icons-vue vue-router

  2. 全局配置(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')

二、登录页面核心实现
  1. 模板结构(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>
  2. 数据与验证逻辑

    <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>

  3. 样式优化要点

    
    <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>

三、进阶功能实现
  1. 路由守卫配置

    // 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'
      }
    })

  2. 安全增强方案

    • 密码加密传输(使用crypto-js)

    • 添加验证码功能

    • 请求限流与防重放攻击

    import CryptoJS from 'crypto-js'
    
    const encryptPassword = (password) => {
      return CryptoJS.SHA256(password).toString()
    }

  3. 第三方登录集成

    <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>

四、最佳实践与注意事项
  1. 表单验证优化

    •   异步验证手机号是否注册

    •  密码强度实时检测

    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('验证失败'))
      }
    }

  2. 用户体验优化

    • 自动填充最近登录账号

    • 记住密码功能(加密存储)

    • 加载状态管理

    // 自动填充
    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')
      }
    })

  3. 错误处理规范

    try {
      const res = await loginApi(formData)
      if (res.code === 1001) {
        ElMessage.warning('该账号已被冻结')
      }
    } catch (err) {
      ElMessage.error({
        message: `登录失败: ${err.message}`,
        grouping: true  // 相同错误合并显示
      })
    }

五、典型问题解决方案
  1. 跨域问题处理

    // vite.config.js
    export default defineConfig({
      server: {
        proxy: {
          '/api': {
            target: 'http://backend.example.com',
            changeOrigin: true,
            rewrite: (path) => path.replace(/^\/api/, '')
          }
        }
      }
    })

  2. 响应式布局适配

    @media (max-width: 768px) {
      .login-container {
        padding: 1rem;
        
        :deep(.el-form) {
          width: 100%;
          margin: 0 1rem;
        }
      }
    }

  3. 浏览器兼容问题

    • 使用@vitejs/plugin-legacy处理ES6+语法

    • 添加autoprefixer自动补全CSS前缀


网站公告

今日签到

点亮在社区的每一天
去签到