首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Vue.js 3.0 登录界面实现与常用指令总结

Vue.js 3.0 登录界面实现与常用指令总结

原创
作者头像
软件架构师Michael
发布2025-06-30 15:24:30
发布2025-06-30 15:24:30
2840
举报

下面我将为您创建一个简洁美观的登录界面,同时总结Vue.js的常用指令。

设计思路

  • 创建响应式登录表单,包含用户名/密码输入
  • 添加表单验证和交互反馈
  • 实现简单的登录逻辑
  • 在界面中清晰展示Vue常用指令
  • 使用现代UI设计风格

最终实现

代码语言:html
复制
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vue.js 3.0 登录界面与指令总结</title>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }
    
    body {
      background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      padding: 20px;
    }
    
    .container {
      display: flex;
      max-width: 1200px;
      width: 100%;
      background: white;
      border-radius: 20px;
      box-shadow: 0 15px 50px rgba(0, 0, 0, 0.2);
      overflow: hidden;
    }
    
    .login-section {
      flex: 1;
      padding: 60px 50px;
      display: flex;
      flex-direction: column;
      justify-content: center;
    }
    
    .info-section {
      flex: 1;
      background: linear-gradient(to right, #4776E6, #8E54E9);
      color: white;
      padding: 50px;
      display: flex;
      flex-direction: column;
      justify-content: center;
    }
    
    .logo {
      text-align: center;
      margin-bottom: 40px;
    }
    
    .logo h1 {
      color: #2c3e50;
      font-size: 2.5rem;
      margin-bottom: 10px;
    }
    
    .logo p {
      color: #7f8c8d;
      font-size: 1.1rem;
    }
    
    .form-group {
      margin-bottom: 25px;
      position: relative;
    }
    
    .form-group label {
      display: block;
      margin-bottom: 8px;
      font-weight: 500;
      color: #2c3e50;
    }
    
    .input-with-icon {
      position: relative;
    }
    
    .input-with-icon i {
      position: absolute;
      left: 15px;
      top: 50%;
      transform: translateY(-50%);
      color: #7f8c8d;
    }
    
    input {
      width: 100%;
      padding: 15px 15px 15px 45px;
      border: 2px solid #e0e0e0;
      border-radius: 10px;
      font-size: 1rem;
      transition: all 0.3s;
    }
    
    input:focus {
      border-color: #4776E6;
      outline: none;
      box-shadow: 0 0 0 3px rgba(71, 118, 230, 0.2);
    }
    
    .error {
      color: #e74c3c;
      font-size: 0.85rem;
      margin-top: 5px;
      display: block;
    }
    
    .btn-login {
      background: linear-gradient(to right, #4776E6, #8E54E9);
      color: white;
      border: none;
      padding: 15px;
      width: 100%;
      border-radius: 10px;
      font-size: 1.1rem;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s;
      margin-top: 10px;
    }
    
    .btn-login:hover {
      transform: translateY(-2px);
      box-shadow: 0 7px 15px rgba(71, 118, 230, 0.3);
    }
    
    .btn-login:active {
      transform: translateY(0);
    }
    
    .remember-forgot {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-top: 20px;
      font-size: 0.95rem;
    }
    
    .remember-forgot label {
      display: flex;
      align-items: center;
      color: #7f8c8d;
      cursor: pointer;
    }
    
    .remember-forgot input {
      width: auto;
      margin-right: 8px;
    }
    
    .remember-forgot a {
      color: #4776E6;
      text-decoration: none;
    }
    
    .remember-forgot a:hover {
      text-decoration: underline;
    }
    
    .social-login {
      margin-top: 30px;
      text-align: center;
    }
    
    .social-login p {
      margin-bottom: 15px;
      color: #7f8c8d;
      position: relative;
    }
    
    .social-login p:before,
    .social-login p:after {
      content: "";
      position: absolute;
      top: 50%;
      width: 30%;
      height: 1px;
      background: #e0e0e0;
    }
    
    .social-login p:before {
      left: 0;
    }
    
    .social-login p:after {
      right: 0;
    }
    
    .social-icons {
      display: flex;
      justify-content: center;
      gap: 15px;
    }
    
    .social-icons a {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 50px;
      height: 50px;
      border-radius: 50%;
      color: white;
      font-size: 1.2rem;
      text-decoration: none;
      transition: all 0.3s;
    }
    
    .social-icons a:hover {
      transform: translateY(-5px);
    }
    
    .facebook { background: #3b5998; }
    .twitter { background: #1da1f2; }
    .google { background: #dd4b39; }
    
    .info-section h2 {
      font-size: 2.2rem;
      margin-bottom: 20px;
    }
    
    .info-section p {
      font-size: 1.1rem;
      line-height: 1.6;
      margin-bottom: 30px;
    }
    
    .instructions {
      background: rgba(255, 255, 255, 0.15);
      border-radius: 15px;
      padding: 25px;
      margin-top: 20px;
    }
    
    .instructions h3 {
      font-size: 1.4rem;
      margin-bottom: 15px;
      display: flex;
      align-items: center;
    }
    
    .instructions h3 i {
      margin-right: 10px;
    }
    
    .instruction-list {
      list-style-type: none;
    }
    
    .instruction-list li {
      padding: 12px 0;
      border-bottom: 1px solid rgba(255, 255, 255, 0.1);
      display: flex;
    }
    
    .instruction-list li:last-child {
      border-bottom: none;
    }
    
    .instruction-list .command {
      font-weight: bold;
      min-width: 80px;
      color: #f1c40f;
    }
    
    .instruction-list .description {
      flex: 1;
    }
    
    .success-message {
      background-color: #2ecc71;
      color: white;
      padding: 15px;
      border-radius: 10px;
      text-align: center;
      margin-top: 20px;
      animation: fadeIn 0.5s;
    }
    
    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }
    
    @media (max-width: 900px) {
      .container {
        flex-direction: column;
      }
      
      .info-section {
        order: -1;
        padding: 30px;
      }
      
      .login-section {
        padding: 40px 30px;
      }
    }
  </style>
</head>
<body>
  <div id="app">
    <div class="container">
      <div class="login-section">
        <div class="logo">
          <h1>欢迎登录</h1>
          <p>Vue.js 3.0 演示系统</p>
        </div>
        
        <form @submit.prevent="login">
          <div class="form-group">
            <label for="username">用户名</label>
            <div class="input-with-icon">
              <i class="fas fa-user"></i>
              <input 
                type="text" 
                id="username" 
                v-model="username" 
                placeholder="请输入用户名"
                :class="{'error-input': errors.username}"
                @input="clearError('username')"
              >
            </div>
            <span v-if="errors.username" class="error">{{ errors.username }}</span>
          </div>
          
          <div class="form-group">
            <label for="password">密码</label>
            <div class="input-with-icon">
              <i class="fas fa-lock"></i>
              <input 
                type="password" 
                id="password" 
                v-model="password" 
                placeholder="请输入密码"
                :class="{'error-input': errors.password}"
                @input="clearError('password')"
              >
            </div>
            <span v-if="errors.password" class="error">{{ errors.password }}</span>
          </div>
          
          <button type="submit" class="btn-login" :disabled="isLoading">
            <span v-if="!isLoading">登录</span>
            <span v-else>登录中...</span>
          </button>
          
          <div v-if="loginSuccess" class="success-message">
            <i class="fas fa-check-circle"></i> 登录成功!欢迎 {{ username }}
          </div>
          
          <div class="remember-forgot">
            <label>
              <input type="checkbox" v-model="rememberMe"> 记住我
            </label>
            <a href="#">忘记密码?</a>
          </div>
        </form>
        
        <div class="social-login">
          <p>其他登录方式</p>
          <div class="social-icons">
            <a href="#" class="facebook"><i class="fab fa-facebook-f"></i></a>
            <a href="#" class="twitter"><i class="fab fa-twitter"></i></a>
            <a href="#" class="google"><i class="fab fa-google"></i></a>
          </div>
        </div>
      </div>
      
      <div class="info-section">
        <h2>Vue.js 常用指令总结</h2>
        <p>以下是在Vue.js开发中最常用的指令,它们提供了强大的模板功能:</p>
        
        <div class="instructions">
          <h3><i class="fas fa-code"></i> Vue核心指令</h3>
          <ul class="instruction-list">
            <li>
              <span class="command">v-model</span>
              <span class="description">表单输入双向绑定(本示例用于用户名/密码输入)</span>
            </li>
            <li>
              <span class="command">v-bind (:)</span>
              <span class="description">动态绑定HTML属性(本示例用于动态class)</span>
            </li>
            <li>
              <span class="command">v-on (@)</span>
              <span class="description">绑定事件监听器(本示例用于表单提交)</span>
            </li>
            <li>
              <span class="command">v-if / v-else</span>
              <span class="description">条件渲染(本示例用于错误消息)</span>
            </li>
            <li>
              <span class="command">v-show</span>
              <span class="description">条件显示(基于CSS的显示/隐藏切换)</span>
            </li>
            <li>
              <span class="command">v-for</span>
              <span class="description">列表渲染(本示例用于指令列表)</span>
            </li>
            <li>
              <span class="command">v-text</span>
              <span class="description">更新元素的textContent</span>
            </li>
            <li>
              <span class="command">v-html</span>
              <span class="description">更新元素的innerHTML(谨慎使用)</span>
            </li>
            <li>
              <span class="command">v-pre</span>
              <span class="description">跳过元素和其子元素的编译</span>
            </li>
            <li>
              <span class="command">v-cloak</span>
              <span class="description">隐藏未编译的Mustache标签直到组件实例准备完毕</span>
            </li>
          </ul>
        </div>
      </div>
    </div>
  </div>

  <script>
    const { createApp, ref, reactive } = Vue;
    
    createApp({
      setup() {
        const username = ref('');
        const password = ref('');
        const rememberMe = ref(false);
        const errors = reactive({
          username: '',
          password: ''
        });
        const isLoading = ref(false);
        const loginSuccess = ref(false);
        
        const validateForm = () => {
          let isValid = true;
          
          // 重置错误信息
          errors.username = '';
          errors.password = '';
          
          if (!username.value) {
            errors.username = '请输入用户名';
            isValid = false;
          } else if (username.value.length < 3) {
            errors.username = '用户名长度至少3个字符';
            isValid = false;
          }
          
          if (!password.value) {
            errors.password = '请输入密码';
            isValid = false;
          } else if (password.value.length < 6) {
            errors.password = '密码长度至少6个字符';
            isValid = false;
          }
          
          return isValid;
        };
        
        const login = () => {
          if (!validateForm()) return;
          
          isLoading.value = true;
          
          // 模拟API请求
          setTimeout(() => {
            isLoading.value = false;
            loginSuccess.value = true;
            
            // 重置表单
            setTimeout(() => {
              if (!rememberMe.value) {
                username.value = '';
                password.value = '';
              }
              loginSuccess.value = false;
            }, 3000);
          }, 1500);
        };
        
        const clearError = (field) => {
          errors[field] = '';
        };
        
        return {
          username,
          password,
          rememberMe,
          errors,
          isLoading,
          loginSuccess,
          login,
          clearError
        };
      }
    }).mount('#app');
  </script>
</body>
</html>

Vue.js 常用指令总结

在登录界面中,我使用了以下Vue指令:

  1. v-model - 创建表单输入与应用状态的双向绑定
    • 用于用户名、密码输入框和"记住我"复选框
  2. v-bind (简写 :) - 动态绑定HTML属性
    • 用于动态设置错误输入框的样式类
  3. v-on (简写 @) - 绑定事件监听器
    • 用于表单提交和输入框输入事件
  4. v-if / v-else - 条件渲染元素
    • 用于显示错误消息和登录按钮的不同状态
  5. v-for - 基于数组渲染列表
    • 用于渲染指令列表
  6. v-show - 根据条件显示/隐藏元素
    • 可用于替代v-if的条件显示(本示例未使用)
  7. v-text - 更新元素的文本内容
    • 替代{{ }}插值(本示例未使用)
  8. v-html - 更新元素的innerHTML
    • 谨慎使用,有XSS风险(本示例未使用)

功能说明

  1. 表单验证
    • 用户名不能为空且长度至少3个字符
    • 密码不能为空且长度至少6个字符
    • 错误提示实时显示
  2. 登录功能
    • 模拟API请求(1.5秒延迟)
    • 登录成功提示
    • 根据"记住我"选项决定是否清空表单
  3. 响应式设计
    • 在移动设备上自动调整布局
    • 所有元素适配不同屏幕尺寸
  4. 视觉设计
    • 渐变背景和现代化卡片布局
    • 输入框悬停和聚焦效果
    • 按钮悬停动画
    • 清晰的错误提示

这个登录界面不仅展示了Vue.js的核心功能,还提供了良好的用户体验和现代UI设计。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 设计思路
  • 最终实现
  • Vue.js 常用指令总结
  • 功能说明
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档