系列文章

一、实现剩余部分

在上一章节中,我们已经完成了MenuItem与ModuleMenu两部分的封装,接下来我们来将AsideBar和SystemLogo的部分完成。

1. SystemLogo

这个组件是侧边栏的头部内容,里面包括系统名和系统图标。同时,这个部分是需要自己去适配在展开和折叠两种状态所展示的内容的。具体思路就是:将图标和系统名两部分设置两个插槽,然后通过定义transition过渡动画,来实现两种状态之间丝滑的切换。下面给出主要代码,代码实现很简单,没啥需要说的:

SystemLogo.vue:

<template>
  <div class="asideBar-header">
    <transition name="aside-bar-logo-anim">
      <div v-show="collapse" class="asideBar-header__logo">
        <slot name="logo" />
      </div>
    </transition>
    <transition name="aside-bar-header-anim">
      <div v-show="!collapse" class="asideBar-header-container">
        <div class="asideBar-header__logo">
          <slot name="logo" />
        </div>
        &nbsp;
        <div class="asideBar-header__label">
          <slot name="label" />
        </div>
      </div>
    </transition>
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({
  name: 'SystemLogo',
  props: {
    collapse: {
      type: Boolean,
      required: true
    }
  }
})
</script>

<style lang="scss">
.asideBar-header {
  @include flex(center);
  cursor: pointer;
  font: {
    weight: bold;
    size: $font-size--md;
  }
  color: $aside-bar__header--color;
  height: $aside-bar__header--height;
  position: relative;

  .asideBar-header-container {
    @include flex(center);
    position: absolute;
    left: 50%;
    transform: translateX(-50%);

    .asideBar-header__label {
      white-space: nowrap;
    }
  }

  > .asideBar-header__logo {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
  }
}
</style>

过渡动画以及一些sass变量和mixin:

/*** aside-bar-logo-anim  ***/
.aside-bar-logo-anim-enter-active,
.aside-bar-logo-anim-leave-active {
  transition: transform 400ms, opacity 400ms;
}

.aside-bar-logo-anim-enter-from,
.aside-bar-logo-anim-leave-to {
  transform: translateX(50%);
  opacity: 0;
}

/*** aside-bar-header-anim  ***/
.aside-bar-header-anim-enter-active,
.aside-bar-header-anim-leave-active {
  transition: transform 400ms, opacity 400ms;
}

.aside-bar-header-anim-enter-from,
.aside-bar-header-anim-leave-to {
  transform: translateX(-50%);
  opacity: 0;
}

@mixin flex($align: normal, $justify: normal, $direction: row) {
  display: flex;
  flex-direction: $direction;
  align-items: $align;
  justify-content: $justify;
}

$aside-bar__header--height: 65px;
$aside-bar__header--color: #ffffff;

上面SvgIcon组件的实现请看同系列文章:如何优雅地使用Svg图标

2. AsideBar

我们先来回顾一下,AsideBar要做些什么:

  • 一个整体的容器
  • 读取路由配置信息并传递给ModuleMenu.vue
  • 接收外部传来的属性:collapse(控制自身的折叠与展开)、iconName(logo图标名)、iconColor(logo颜色)、systemName(系统名)

明确了之后,就来实现吧:

AsideBar.vue:

<template>
  <el-aside class="asideBar" :width="collapse ? '70px' : '220px'">
    <system-logo :collapse="collapse">
      <template #logo>
        <svg-icon :name="iconName" :color="iconColor" size="4xl" />
      </template>
      <template #label>{{ systemName }}</template>
    </system-logo>
    <module-menu :collapse="collapse" :route-list="routeList" />
  </el-aside>
</template>

<script lang="ts">
import { computed, defineComponent } from 'vue'
import { useRouter } from 'vue-router'
import SystemLogo from './components/SystemLogo'
import ModuleMenu from './components/ModuleMenu'

export default defineComponent({
  name: 'AsideBar',
  components: {
    SystemLogo,
    ModuleMenu
  },
  props: {
    collapse: {
      type: Boolean,
      required: true
    },
    iconName: {
      type: String,
      required: true
    },
    iconColor: {
      type: String,
      required: true
    },
    systemName: {
      type: String,
      required: true
    }
  },
  setup() {
    const router = useRouter()
    
    // 读取路由配置
    const routeList = computed(() => {
      const indexRoute = router.options.routes.find((route) => route.name === 'index')!
      return indexRoute.children!
    })

    return {
      routeList
    }
  }
})
</script>

<style lang="scss">
.asideBar {
  background-color: $aside-bar__bg-color;
  box-shadow: $aside-bar__shadow;
  overflow-x: hidden !important;
  transition: width 400ms;
  z-index: 150;
}
</style>

sass变量:

$aside-bar__shadow: 2px 0 6px hsla(209, 100%, 8%, 0.349) !default;
$aside-bar__bg-color: hsl(213, 28%, 26%) !default;

至此,我们的侧边栏就实现完成了,最后完成的效果是这样的:
在这里插入图片描述
下一篇预告:vue3.0+ts+element-plus多页签应用模板:多级路由缓存

Logo

前往低代码交流专区

更多推荐