携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情
搭建Layout架构 解决方案与实现
业务落地:修复最后的残余问题
目前 menu 菜单还存在三个问题
1、样式问题
2、路由跳转问题
3、默认激活项
- 样式问题
由于后边我们的主题肯定是需要替换的,所以样式我们不能写死
在 store/getters 中创建一个新的访问方式
import variables from '@/styles/variables.scss'
const getters = {
cssVar: state => variables
}
export default getters
在 SiderbarMenu 中写入如下样式
<el-menu
:background-color="$store.getters.cssVar.menuBg"
:text-color="$store.getters.cssVar.menuText"
:active-text-color="$store.getters.cssVar.menuActiveText"
:unique-opened="true"
>
- 路由跳转问题
<el-menu
router
>
- 默认激活项
<el-menu
:default-active="activeMenu"
>
<script setup>
// 计算高亮 menu 的方法
const route = useRoute()
const activeMenu = computed(() => {
const { path } = route
return path
})
</script>
动画逻辑,左侧菜单伸缩功能实现
下边我们来实现一个标准化的功能左侧菜单伸缩,这个功能的核心在于动画处理
创建 store/app 模块,写入如下代码
export default {
namespaced: true,
state: () => ({
sidebarOpened: true
}),
mutations: {
triggerSidebarOpened(state) {
state.sidebarOpened = !state.sidebarOpened
}
},
actions: {}
}
在 store/index 中进行导入
import app from './modules/app'
export default createStore({
getters,
modules: {
...
app
}
})
在 store/getters 中创建新的访问方式
sidebarOpened: state => state.app.sidebarOpened
创建 components/hamburger 组件,用来控制数据
<template>
<div class="hamburger-container" @click="toggleClick">
<svg-icon class="hamburger" :icon="icon"></svg-icon>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useStore } from 'vuex'
const store = useStore()
const toggleClick = () => {
store.commit('app/triggerSidebarOpened')
}
const icon = computed(() =>
store.getters.sidebarOpened ? 'hamburger-opened' : 'hamburger-closed'
)
</script>
<style lang="scss" scoped>
.hamburger-container {
padding: 0 16px;
.hamburger {
display: inline-block;
vertical-align: middle;
width: 20px;
height: 20px;
}
}
</style>
在 navbar 中使用该组件
<template>
<div class="navbar">
<hamburger class="hamburger-container" />
...
</div>
</template>
<script setup>
import Hamburger from '@/components/Hamburger'
...
</script>
<style lang="scss" scoped>
.navbar {
.hamburger-container {
line-height: 46px;
height: 100%;
float: left;
cursor: pointer;
// hover 动画
transition: background 0.5s;
&:hover {
background: rgba(0, 0, 0, 0.1);
}
}
}
</style>
在 SidebarMenu 中,控制 el-menu 的 collapse 属性
<el-menu
:collapse="!$store.getters.sidebarOpened">
</el-menu>
在 layout/index 中指定整个侧边栏的宽度和缩放动画
<div
class="app-wrapper"
:class="[$store.getters.sidebarOpened ? 'openSidebar' : 'hideSidebar']"
>
在 layout/index 中 处理 navbar 的宽度
<style lang="scss" scoped>
.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$sideBarWidth});
transition: width 0.28s;
}
.hideSidebar .fixed-header {
width: calc(100% - #{$hideSideBarWidth});
}
</style>
在 styles/variables.scss 中指定 hideSideBarWidth
$hideSideBarWidth: 54px;
SidebarHeader 处理
在 sidebar/index 中写入如下代码
<template>
<div class="">
<div class="logo-container">
<el-avatar
size="44"
shape="square"
src="xxx"
/>
<h1 class="logo-title" v-if="$store.getters.sidebarOpened">
imooc-admin
</h1>
</div>
...
</div>
</template>
<style lang="scss" scoped>
.logo-container {
height: 44px;
padding: 10px 0 22px 0;
display: flex;
align-items: center;
justify-content: center;
.logo-title {
margin-left: 10px;
color: #fff;
font-weight: 600;
line-height: 50px;
font-size: 16px;
white-space: nowrap;
}
}
</style>
创建 styles/element.scss 文件,统一处理 el-avatar 的背景问题
.el-avatar {
--el-avatar-background-color: none;
}
在 styles/index.scss 中导入
@import './element.scss';
统一处理下动画时长的问题,在 styles/variables.scss 中,加入以下变量
$sideBarDuration: 0.28s;
为 styles/sidebar.scss 修改时长
.main-container {
transition: margin-left #{$sideBarDuration};
}
.sidebar-container {
transition: width #{$sideBarDuration};
}
为 layout/index 修改样式
.fixed-header {
transition: width #{$sideBarDuration};
}