🔥一招搞定!Vue3通用布局+菜单组件:让你的项目颜值与效率齐飞!🚀

Python私教 2025-01-12 08:31:44

我们将基于之前的 Layout.vue 组件,扩展出一个包含顶部菜单和左侧菜单的布局。顶部菜单分为左、中、右三部分,左侧是纯文字 Logo(“Python私教”),中间是常用菜单(如首页、关于等),右侧是注册、登录等按钮。左侧菜单则是一个多级菜单,支持展开和折叠。

最终效果图:实现效果

顶部菜单:

左侧:文字 Logo(“Python私教”)。中间:常用菜单(首页、关于等)。右侧:注册、登录等按钮。

左侧菜单:

支持多级菜单。支持展开和折叠。

布局结构:

顶部菜单固定在页面顶部。左侧菜单固定在页面左侧。主体内容在右侧,可以滚动。实现代码1. 修改 Layout.vue 组件

<template>  <div class="layout" :class="`theme-${theme}`">    <!-- 顶部菜单 -->    <header class="header">      <div class="header-left">        <span class="logo">Python私教</span>      </div>      <div class="header-center">        <ul class="top-menu">          <li v-for="item in topMenuData" :key="item.label" class="top-menu-item">            {{ item.label }}          </li>        </ul>      </div>      <div class="header-right">        <button class="btn">注册</button>        <button class="btn">登录</button>      </div>    </header>    <div class="main-container">      <!-- 左侧菜单 -->      <aside class="sidebar">        <Menu :menuData="leftMenuData" />      </aside>      <!-- 主体内容 -->      <main class="content">        <slot></slot>      </main>    </div>  </div></template><script setup>import { ref } from 'vue';import Menu from './Menu.vue'; // 导入菜单组件const props = defineProps({  theme: {    type: String,    default: 'light',    validator: (value) => ['light', 'dark'].includes(value),  },});// 顶部菜单数据const topMenuData = ref([  { label: '首页' },  { label: '关于我们' },  { label: '服务' },  { label: '联系我们' },]);// 左侧菜单数据const leftMenuData = ref([  {    label: '首页',    icon: 'fas fa-home',  },  {    label: '关于我们',    icon: 'fas fa-info-circle',  },  {    label: '服务',    icon: 'fas fa-cogs',    children: [      { label: '服务1', icon: 'fas fa-wrench' },      { label: '服务2', icon: 'fas fa-wrench' },    ],  },]);</script><style scoped>.layout {  display: flex;  flex-direction: column;  min-height: 100vh;}.header {  display: flex;  justify-content: space-between;  align-items: center;  padding: 0 20px;  background-color: #007bff;  color: white;  height: 60px;  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);}.header-left .logo {  font-size: 20px;  font-weight: bold;}.header-center .top-menu {  display: flex;  list-style: none;  margin: 0;  padding: 0;}.top-menu-item {  margin: 0 15px;  cursor: pointer;}.top-menu-item:hover {  text-decoration: underline;}.header-right .btn {  margin-left: 10px;  padding: 5px 10px;  border: none;  border-radius: 4px;  background-color: white;  color: #007bff;  cursor: pointer;}.header-right .btn:hover {  background-color: #f0f0f0;}.main-container {  display: flex;  flex: 1;}.sidebar {  width: 250px;  background-color: #f8f9fa;  border-right: 1px solid #ddd;  overflow-y: auto;}.content {  flex: 1;  padding: 20px;  overflow-y: auto;}/* 浅色主题 */.theme-light {  background-color: #ffffff;  color: #333333;}.theme-light .sidebar {  background-color: #f8f9fa;}/* 深色主题 */.theme-dark {  background-color: #1a1a1a;  color: #ffffff;}.theme-dark .sidebar {  background-color: #2d2d2d;}</style>

2. 创建 Menu.vue 组件

<template>  <ul class="menu">    <li v-for="item in menuData" :key="item.label" class="menu-item">      <!-- 菜单项 -->      <div class="menu-label" @click="toggleSubMenu(item)">        <span v-if="item.icon" class="menu-icon">          <i :class="item.icon"></i>        </span>        <span class="menu-text">{{ item.label }}</span>        <span v-if="item.children" class="menu-arrow">          {{ isSubMenuOpen(item) ? '▼' : '▶' }}        </span>      </div>      <!-- 子菜单 -->      <ul v-if="item.children && isSubMenuOpen(item)" class="sub-menu">        <li          v-for="child in item.children"          :key="child.label"          class="sub-menu-item"        >          <span v-if="child.icon" class="menu-icon">            <i :class="child.icon"></i>          </span>          <span class="menu-text">{{ child.label }}</span>        </li>      </ul>    </li>  </ul></template><script setup>import { ref } from 'vue';const props = defineProps({  menuData: {    type: Array,    required: true,  },});const openMenus = ref([]);// 切换子菜单展开/收起const toggleSubMenu = (item) => {  if (item.children) {    const index = openMenus.value.indexOf(item.label);    if (index === -1) {      openMenus.value.push(item.label);    } else {      openMenus.value.splice(index, 1);    }  }};// 判断子菜单是否展开const isSubMenuOpen = (item) => {  return openMenus.value.includes(item.label);};</script><style scoped>.menu {  list-style: none;  padding: 0;  margin: 0;}.menu-item {  margin: 8px 0;}.menu-label {  display: flex;  align-items: center;  padding: 8px 16px;  cursor: pointer;  transition: background-color 0.3s ease;}.menu-label:hover {  background-color: rgba(0, 0, 0, 0.1);}.menu-icon {  margin-right: 8px;}.menu-text {  flex: 1;}.menu-arrow {  margin-left: 8px;}.sub-menu {  list-style: none;  padding-left: 24px;  margin: 0;}.sub-menu-item {  padding: 8px 16px;  cursor: pointer;  transition: background-color 0.3s ease;}.sub-menu-item:hover {  background-color: rgba(0, 0, 0, 0.1);}</style>

使用示例

<template>  <Layout theme="light">    <div>这里是主体内容</div>  </Layout></template><script setup>import Layout from './Layout.vue';</script>

加入我们的学习社区,一起成长!

如果你觉得这个组件很棒,欢迎私信我,加入我们的学习社区!在这里,你可以:

学习更多前端开发技巧。参与开源项目,提升实战能力。和志同道合的开发者一起交流。

私信我,获取更多实用教程和资源!👉 发送私信【通用菜单组件】,我会分享完整代码和更多学习资料!👉 也可以私信我【加入社区】,拉你进我们的开发者交流群,一起探讨技术!

结语

通过结合 Layout.vue 和 Menu.vue,我们实现了一个功能强大的布局组件,支持顶部菜单和左侧菜单。希望这篇文章能帮到你,也期待你在评论区分享你的想法和改进建议!

记住,代码的世界里,分享即是成长! 😄

0 阅读:0

Python私教

简介:全栈工程师,目标人工智能.抖音同理想国真恵玩.