5.6.13 • Published 5 months ago
@cimom/vben-effects-layouts v5.6.13
@cimom/vben-effects-layouts
提供多种布局组件和布局系统,用于构建管理系统的整体页面结构。该包继承了核心布局组件的能力,并扩展了更多业务场景下的布局方案。
安装
# 进入目标应用目录,例如 apps/xxxx-app
# cd apps/xxxx-app
pnpm add @cimom/vben-effects-layouts基本使用
// 导入布局组件
import {
BasicLayout,
AuthenticationLayout,
IframeLayout,
} from '@cimom/vben-effects-layouts';
// 导入布局小部件
import {
HeaderLogo,
HeaderMenu,
SideMenu,
TabBar,
} from '@cimom/vben-effects-layouts';布局类型
BasicLayout 基础布局
提供标准的管理系统布局,包含顶部导航栏、侧边菜单、标签页和内容区域。
<template>
<BasicLayout>
<template #header-left-1>
<HeaderLogo />
</template>
<template #header-left-2>
<HeaderMenu />
</template>
<template #header-right-1>
<ThemeToggle />
</template>
<template #header-right-2>
<UserDropdown />
</template>
<!-- 路由视图 -->
<router-view />
</BasicLayout>
</template>
<script setup lang="ts">
import {
BasicLayout,
HeaderLogo,
HeaderMenu,
ThemeToggle,
UserDropdown,
} from '@cimom/vben-effects-layouts';
</script>插槽说明
BasicLayout 提供了丰富的插槽,用于自定义布局的各个部分:
- header-left-n: 顶部导航栏左侧插槽,n 为 0-19 的数字,breadcrumb 为 21-x
- header-right-n: 顶部导航栏右侧插槽,n 为 0-49,其他特定组件有固定范围:
- global-search: 50
- theme-toggle: 51-59
- language-toggle: 61-69
- fullscreen: 71-79
- notification: 81-89
- user-dropdown: 91-149
- 其他自定义组件: 151-x
- menu: 自定义整个菜单区域
- footer: 自定义页脚区域
- content: 自定义内容区域
- tabbar: 自定义标签页区域
属性说明
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
showLogo | boolean | true | 是否显示 Logo |
showFooter | boolean | true | 是否显示页脚 |
showBreadcrumb | boolean | true | 是否显示面包屑 |
showTabs | boolean | true | 是否显示标签页 |
showSidebar | boolean | true | 是否显示侧边栏 |
showHeader | boolean | true | 是否显示顶部导航栏 |
fixedHeader | boolean | true | 是否固定顶部导航栏 |
fixedSidebar | boolean | true | 是否固定侧边栏 |
contentMode | 'full' \| 'fixed' | 'fixed' | 内容区域模式 |
menuMode | 'vertical' \| 'horizontal' \| 'inline' | 'vertical' | 菜单模式 |
menuTheme | 'light' \| 'dark' | 'light' | 菜单主题 |
menuWidth | number | 210 | 菜单宽度 |
collapsedWidth | number | 48 | 菜单折叠时的宽度 |
collapsed | boolean | false | 是否折叠菜单 |
AuthenticationLayout 认证布局
提供登录、注册、找回密码等认证页面的布局。
<template>
<AuthenticationLayout
:title="title"
:desc="desc"
:backgroundUrl="backgroundUrl"
>
<LoginForm @login="handleLogin" />
</AuthenticationLayout>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { AuthenticationLayout } from '@cimom/vben-effects-layouts';
import { LoginForm } from '@/components/login-form';
const title = ref('系统登录');
const desc = ref('欢迎使用管理系统');
const backgroundUrl = ref('/images/login-bg.jpg');
const handleLogin = (formData) => {
// 处理登录逻辑
};
</script>属性说明
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | string | '' | 标题 |
desc | string | '' | 描述文本 |
backgroundUrl | string | '' | 背景图片 URL |
logoUrl | string | '' | Logo URL |
showLanguageToggle | boolean | true | 是否显示语言切换 |
showThemeToggle | boolean | true | 是否显示主题切换 |
IframeLayout Iframe 布局
提供嵌入外部网页的布局。
<template>
<IframeLayout :src="iframeSrc" />
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { IframeLayout } from '@cimom/vben-effects-layouts';
const iframeSrc = ref('https://example.com');
</script>属性说明
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
src | string | '' | iframe 的 src 属性 |
loading | boolean | false | 是否显示加载状态 |
height | string \| number | '100%' | iframe 高度 |
width | string \| number | '100%' | iframe 宽度 |
布局小部件
顶部导航栏组件
HeaderLogo 顶部 Logo
<template>
<HeaderLogo :showTitle="true" :logo="logoUrl" :title="title" />
</template>
<script setup lang="ts">
import { HeaderLogo } from '@cimom/vben-effects-layouts';
const logoUrl = '/logo.png';
const title = '管理系统';
</script>HeaderMenu 顶部菜单
<template>
<HeaderMenu :menus="menus" />
</template>
<script setup lang="ts">
import { HeaderMenu } from '@cimom/vben-effects-layouts';
const menus = [
{
path: '/dashboard',
title: '仪表盘',
icon: 'dashboard',
},
{
path: '/system',
title: '系统管理',
icon: 'setting',
children: [
{
path: '/system/user',
title: '用户管理',
},
{
path: '/system/role',
title: '角色管理',
},
],
},
];
</script>Breadcrumb 面包屑
<template>
<Breadcrumb :items="breadcrumbItems" />
</template>
<script setup lang="ts">
import { Breadcrumb } from '@cimom/vben-effects-layouts';
const breadcrumbItems = [
{ title: '首页', path: '/' },
{ title: '系统管理', path: '/system' },
{ title: '用户管理', path: '/system/user' },
];
</script>侧边栏组件
SideMenu 侧边菜单
<template>
<SideMenu
:menus="menus"
:collapsed="collapsed"
:theme="menuTheme"
@select="handleMenuSelect"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { SideMenu } from '@cimom/vben-effects-layouts';
const collapsed = ref(false);
const menuTheme = ref('light');
const menus = [
// 菜单数据...
];
const handleMenuSelect = (key) => {
console.log('Selected menu:', key);
};
</script>标签页组件
TabBar 标签页
<template>
<TabBar
:tabs="tabs"
:activeKey="activeTabKey"
@change="handleTabChange"
@close="handleTabClose"
/>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { TabBar } from '@cimom/vben-effects-layouts';
const tabs = ref([
{ key: '/dashboard', title: '仪表盘' },
{ key: '/system/user', title: '用户管理' },
]);
const activeTabKey = ref('/dashboard');
const handleTabChange = (key) => {
activeTabKey.value = key;
};
const handleTabClose = (key) => {
tabs.value = tabs.value.filter((tab) => tab.key !== key);
};
</script>其他组件
ThemeToggle 主题切换
<template>
<ThemeToggle />
</template>
<script setup lang="ts">
import { ThemeToggle } from '@cimom/vben-effects-layouts';
</script>LanguageToggle 语言切换
<template>
<LanguageToggle />
</template>
<script setup lang="ts">
import { LanguageToggle } from '@cimom/vben-effects-layouts';
</script>FullscreenToggle 全屏切换
<template>
<FullscreenToggle />
</template>
<script setup lang="ts">
import { FullscreenToggle } from '@cimom/vben-effects-layouts';
</script>UserDropdown 用户下拉菜单
<template>
<UserDropdown :user="user" @logout="handleLogout" />
</template>
<script setup lang="ts">
import { UserDropdown } from '@cimom/vben-effects-layouts';
const user = {
name: 'Admin',
avatar: '/avatar.jpg',
};
const handleLogout = () => {
// 处理登出逻辑
};
</script>高级用法
自定义布局
通过组合使用布局组件和小部件,可以创建自定义的布局:
<template>
<BasicLayout
:menuMode="menuMode"
:collapsed="collapsed"
:showTabs="showTabs"
:showFooter="showFooter"
>
<!-- 自定义顶部左侧区域 -->
<template #header-left-1>
<HeaderLogo :showTitle="!collapsed" />
</template>
<template #header-left-2>
<Breadcrumb v-if="menuMode === 'vertical'" />
<HeaderMenu v-else :menus="menus" />
</template>
<!-- 自定义顶部右侧区域 -->
<template #header-right-1>
<FullscreenToggle />
</template>
<template #header-right-2>
<ThemeToggle />
</template>
<template #header-right-3>
<LanguageToggle />
</template>
<template #header-right-4>
<UserDropdown :user="user" @logout="handleLogout" />
</template>
<!-- 自定义页脚 -->
<template #footer>
<div class="custom-footer">
© {{ new Date().getFullYear() }} My Company
</div>
</template>
<!-- 路由视图 -->
<router-view v-slot="{ Component }">
<transition name="fade" mode="out-in">
<component :is="Component" />
</transition>
</router-view>
</BasicLayout>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import {
BasicLayout,
HeaderLogo,
Breadcrumb,
HeaderMenu,
FullscreenToggle,
ThemeToggle,
LanguageToggle,
UserDropdown,
} from '@cimom/vben-effects-layouts';
const menuMode = ref('vertical');
const collapsed = ref(false);
const showTabs = ref(true);
const showFooter = ref(true);
const menus = [
/* 菜单数据 */
];
const user = { name: 'Admin', avatar: '/avatar.jpg' };
const handleLogout = () => {
// 处理登出逻辑
};
</script>
<style scoped>
.custom-footer {
text-align: center;
padding: 16px;
}
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>响应式布局
布局组件支持响应式设计,可以根据屏幕尺寸自动调整:
<template>
<BasicLayout
:menuMode="isMobile ? 'vertical' : menuMode"
:collapsed="isMobile || collapsed"
:showTabs="!isMobile && showTabs"
>
<!-- 布局内容 -->
</BasicLayout>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { BasicLayout } from '@cimom/vben-effects-layouts';
import { useIsMobile } from '@cimom/vben-effects-hooks';
const menuMode = ref('horizontal');
const collapsed = ref(false);
const showTabs = ref(true);
const { isMobile } = useIsMobile();
</script>动态切换布局
可以根据路由或用户偏好动态切换布局:
<template>
<component :is="layoutComponent">
<router-view />
</component>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import {
BasicLayout,
AuthenticationLayout,
IframeLayout,
} from '@cimom/vben-effects-layouts';
const route = useRoute();
const layoutComponent = computed(() => {
const layoutType = route.meta.layout;
switch (layoutType) {
case 'auth':
return AuthenticationLayout;
case 'iframe':
return IframeLayout;
default:
return BasicLayout;
}
});
</script>与其他包的集成
与 @cimom/vben-stores 集成
<script setup lang="ts">
import { BasicLayout } from '@cimom/vben-effects-layouts';
import { useUserStore, useMenuStore, useTabStore } from '@cimom/vben-stores';
const userStore = useUserStore();
const menuStore = useMenuStore();
const tabStore = useTabStore();
// 使用 store 中的数据
const menus = menuStore.menus;
const tabs = tabStore.tabs;
const user = userStore.userInfo;
</script>与 @cimom/vben-preferences 集成
<script setup lang="ts">
import { BasicLayout } from '@cimom/vben-effects-layouts';
import { usePreferences } from '@cimom/vben-preferences';
const { preferences, updatePreferences } = usePreferences();
// 根据用户偏好设置布局
const menuMode = computed(() => preferences.menuMode || 'vertical');
const menuTheme = computed(() => preferences.menuTheme || 'light');
const collapsed = computed(() => preferences.collapsed || false);
// 更新用户偏好
const toggleCollapsed = () => {
updatePreferences({
collapsed: !collapsed.value,
});
};
</script>注意事项
- 布局组件依赖于多个核心组件包,确保它们已正确安装。
- 使用
BasicLayout时,建议在路由配置中设置相应的元数据,以便自动生成面包屑和标签页。 - 响应式布局需要配合
@cimom/vben-effects-hooks中的useIsMobile等钩子使用。 - 自定义插槽时,注意插槽名称的命名规则,特别是顶部导航栏的左右侧插槽。
常见问题
布局组件不显示或样式错乱
确保已正确导入样式文件,可以在入口文件中全局导入:
// main.ts
import '@cimom/vben-effects-layouts/dist/style.css';菜单项不显示
检查菜单数据格式是否正确,以及是否与路由配置匹配:
// 正确的菜单数据格式
const menus = [
{
path: '/dashboard',
title: '仪表盘',
icon: 'dashboard',
},
{
path: '/system',
title: '系统管理',
icon: 'setting',
children: [
{
path: '/system/user',
title: '用户管理',
},
],
},
];标签页不自动生成
确保路由配置中包含正确的元数据:
// router.ts
const routes = [
{
path: '/dashboard',
component: () => import('./views/dashboard/index.vue'),
meta: {
title: '仪表盘',
icon: 'dashboard',
affix: true, // 固定标签页
},
},
];