当前位置: 首页 > news >正文

Vue3-Element-Admin 登录页布局切换器

Vue3-Element-Admin 登录页布局切换器(Login Layout Switcher)

概述

登录页支持三种布局模式切换:居左(left)居中(center)居右(right),用户选择后自动持久化到localStorage,刷新页面保持上次选择。

灵感来源:Vben5 Admin 登录页

涉及文件

文件类型说明
src/views/login/components/AuthLayoutSwitch.vue新增布局切换下拉组件
src/views/login/index.vue修改登录页主视图,集成布局切换

架构设计

┌─────────────────────────────────────────────────┐ │ login/index.vue │ │ │ │ authLayout = useStorage("auth-layout", "right")│ │ │ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ AuthLayoutSwitch │◄── v-model="authLayout" │ │ │ (Dropdown 组件) │ │ │ └──────────────────┘ │ │ │ │ │ ▼ │ │ :class="`auth-view--${authLayout}`" │ │ │ │ │ ├── .auth-view--left → 表单居左 │ │ ├── .auth-view--center → 表单居中 │ │ └── .auth-view--right → 表单居右(默认) │ └─────────────────────────────────────────────────┘

组件详解

AuthLayoutSwitch.vue

布局切换下拉组件,基于 Element Plusel-dropdown实现。

核心设计:

  • 使用defineModel<AuthLayout>()实现双向绑定
  • 导出AuthLayout类型供父组件使用
  • 三种布局对应三个@element-plus/icons-vue图标:
    • Postcard→ 居左
    • Tickets→ 居中
    • CreditCard→ 居右
<template> <el-dropdown trigger="click" @command="handleCommand"> <el-icon :size="20"> <component :is="layoutIcons[modelValue]" /> </el-icon> <template #dropdown> <el-dropdown-menu> <el-dropdown-item v-for="item in layoutOptions" :key="item.value" :command="item.value" :disabled="modelValue === item.value" > <el-icon> <component :is="item.icon" /> </el-icon> {{ item.label }} </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </template> <script setup lang="ts"> import { Postcard, Tickets, CreditCard } from "@element-plus/icons-vue"; export type AuthLayout = "left" | "center" | "right"; const modelValue = defineModel<AuthLayout>({ default: "right" }); const layoutIcons: Record<AuthLayout, typeof Postcard> = { left: Postcard, center: Tickets, right: CreditCard, }; const layoutOptions = [ { label: "居左", value: "left" as AuthLayout, icon: Postcard }, { label: "居中", value: "center" as AuthLayout, icon: Tickets }, { label: "居右", value: "right" as AuthLayout, icon: CreditCard }, ]; function handleCommand(val: AuthLayout) { modelValue.value = val; } </script>

login/index.vue 集成

Template 关键改动:

<!-- 根元素动态 class --> <div class="auth-view" :class="`auth-view--${authLayout}`"> <!-- 工具栏中加入布局切换 --> <el-tooltip content="视图布局" placement="bottom"> <div class="toolbar-item"> <AuthLayoutSwitch v-model="authLayout" /> </div> </el-tooltip> <!-- 居中模式隐藏产品介绍区域 --> <section v-if="authLayout !== 'center'" class="auth-feature"> ... </section>

Script 关键改动:

import{useStorage}from"@vueuse/core";importAuthLayoutSwitchfrom"./components/AuthLayoutSwitch.vue";importtype{AuthLayout}from"./components/AuthLayoutSwitch.vue";// localStorage 持久化,key: "auth-layout",默认值: "right"constauthLayout=useStorage<AuthLayout>("auth-layout","right");

三种布局模式 CSS 实现

居右(默认)

默认 CSS Grid 布局,产品介绍在左,登录表单在右。

.auth-view--right { .auth-panel { justify-self: end; } }

居左

利用 CSSdirection: rtl技巧反转 Grid 子元素顺序,使登录表单出现在左侧。

.auth-view--left { .auth-view__wrapper { direction: rtl; // 反转子元素排列方向 > * { direction: ltr; // 子元素内部文字方向恢复正常 } } .auth-panel { justify-self: start; } }

为什么用direction: rtl而不是order

  • order需要给每个子元素单独设置
  • direction: rtl一行代码反转所有子元素,更简洁
  • 通过> * { direction: ltr }确保内部文本不受影响

居中

隐藏产品介绍区域(通过v-if),wrapper 改为 flex 居中。

.auth-view--center { .auth-view__wrapper { display: flex; align-items: center; justify-content: center; } .auth-panel { justify-self: center; } }

持久化方案

使用@vueuse/coreuseStorage实现 localStorage 自动读写:

constauthLayout=useStorage<AuthLayout>("auth-layout","right");
  • 存储 keyauth-layout
  • 默认值"right"
  • 类型安全:泛型约束为AuthLayout = "left" | "center" | "right"
  • 自动同步:值变更时自动写入 localStorage,页面加载时自动读取

响应式适配

移动端(≤768px)自动隐藏产品介绍区域,登录表单全宽显示:

@media (max-width: 768px) { .auth-feature { display: none; } .auth-panel { width: 100%; } }

工具栏在小屏(≤640px)固定在右上角:

@media (max-width: 640px) { .auth-view__toolbar { position: fixed; top: 12px; right: 16px; z-index: 20; } }

踩坑记录

stylelintno-descending-specificity报错

问题:布局模式 CSS 块(.auth-view--left .auth-panel等)最初放在基础.auth-panel选择器之前,导致 stylelint 报错:

Expected selector ".auth-panel" to come before selector ".auth-view--left .auth-panel"

原因:stylelint 的no-descending-specificity规则要求低特异性选择器必须出现在高特异性选择器之前。

解决:将布局模式块移到所有.auth-panel及其子选择器(.auth-panel__brand.auth-panel__footer等)之后,@keyframes之前。

CSS 选择器正确顺序

.auth-panel ← 基础选择器(先) .dark .auth-panel ← 主题变体 .auth-panel__brand ← 子选择器 .auth-panel__logo-wrap .auth-panel__logo ... .auth-panel__footer ← ↓ 布局模式块放在这里 ↓ .auth-view--left ← 包含 .auth-panel 的高特异性选择器(后) .auth-view--center .auth-view--right @keyframes ← 动画

依赖

依赖用途
@vueuse/coreuseStorage持久化
@element-plus/icons-vuePostcard/Tickets/CreditCard图标
element-plusel-dropdown/el-tooltip组件
http://www.jsqmd.com/news/1277764/

相关文章:

  • SpringBoot+Vue3+MyBatis选课系统架构与优化实践
  • Linux 7.2内核slab分配器优化:延迟构建freelist实现70%性能提升
  • Java+Vue全栈宠物商城技术架构与实现
  • (2026最新)大连本地漏水检测维修公司靠谱推荐:正规防水补漏上门维修-墙面/屋顶/外墙/暗管漏水检测精准定位 - 即刻修防水
  • Kimi LeetCode 3743. 循环划分的最大得分 Python3实现
  • 企业级本地大语言模型管理架构:构建可扩展的AI部署技术方案
  • 2026年业务数据报表设计器推荐:功能与易用性解析 - 科技焦点
  • 2026年威海汽车电路维修专业服务商联系与选型指南 - 装修教育财税推荐2026
  • 终极揭秘:如何让老款Mac完美运行最新macOS系统?
  • @DateTimeFormat 与 @JsonFormat 详解
  • 拓竹A1C 3D打印机:工科生高速打印入门指南与项目实践
  • 数学建模优化水系电解液配方的核心方法与工程实践
  • 铌酸锂LNOI法诺共振仿真与优化实践
  • 微软Build 2026:Windows原生支持AI智能体,开启操作系统新范式
  • Python项目代码骨架构建与目标函数设计实践
  • Python模拟DDoS攻击与防御:本地实验环境搭建与原理剖析
  • 从滁州出发西藏,怎么选靠谱旅行社?这份避坑攻略(含西藏研学旅行社推荐)| 附:旅行社电话 - 西藏康泰旅行社
  • AI绘画工作流优化:infinite-canvas本地部署与批量出图实战
  • Obsidian模板终极指南:17个免费模板3分钟打造高效知识管理系统
  • BlackHole免费终极指南:3步解锁macOS音频魔法,彻底告别音频孤岛
  • ComfyUI+Wan2.2:AI视频生成工作流部署与电影级镜头实战
  • TPIC7710EVM评估板实战指南:从安全操作到电机驱动验证
  • 数据分析自学指南:从Excel到Python的完整技能栈与实战路径
  • 核心期刊投稿AI率卡在28%怎么办?免费3步压到10%以内,CSSCI北大核心亲测达标
  • 深度解析Qwen Code:5步实现AI编程助手的终极VS Code集成方案
  • Spring Boot设计模式实战:工厂与单例模式解析
  • Kimi LeetCode 3748. 统计稳定子数组的数目 Java实现
  • PlayIntegrityFix完整指南:解决Android设备Play Integrity认证问题的终极方案
  • DeepSWE基准测试解析:GPT-5.6 Sol与Opus 5在软件工程任务中的表现对比
  • ZotMoov 终极指南:如何高效管理 Zotero 附件,释放文献库空间