简单封装侧边可收起面板(Vue)

1,597 阅读1分钟

前言

在后台管理系统中,可能会有类似查看文章或其它文件读取进行操作等功能,本身后台管理系统页面除去侧边菜单栏的宽度后,剩余的可操作空间就变得比较少,当页面内存在文件列表查看文章等类似功能后,还需放置其它内容时,空间就十分不足了。

如果侧边类似文件列表的内容在进行其它操作时不需要展示,那么将其收起到一边可能会更方便内容的呈现。

实际需求

目前分析所需的是,侧边内容在操作后一段时间内不需要呈现,以将更大的空间给主要内容呈现区或操作区。这其实跟管理系统的收起侧边栏非常相似。

代码结构

基本结构

需求的最基本内容就是有两个容器,一个是侧边容器,放置少操作的内容,一个是主要容器,是内容呈现区或操作区

<template>
  <div class="side-pane">
    <!-- 侧边内容 -->
    <div class="side-pane-left">
    </div>

    <!-- 主体内容 -->
    <div class="side-pane-main">
    </div>
  </div>
</template>

直接上代码

补充内容,一般这类面板都需要个header来设置title,还有主体内容区,所以主次容器都同样设计。侧边内容的宽度根据具体需求设置,可传具体值(如:side-width="200px")或传百分比(如:side-width="20%")。

<template>
  <div class="side-pane" :class="{ 'fold': fold }" :style="{ height }">
  
    <!-- 侧边内容 -->
    <div class="side-pane-left" :style="{ width: sideWidth }">
      <transition name="side-pane-left">
        <div class="side-pane-left-con" v-if="!fold">
          <div class="side-pane-left-header" v-if="$slots.leftHeader">
            <slot name="leftHeader"></slot>
          </div>

          <!-- 侧边主体内容区 -->
          <div class="side-pane-left-body">
            <slot name="left"></slot>
          </div>

          <el-button class="fold-btn" type="text" icon="el-icon-arrow-left" @click="changeFold"></el-button>
        </div>
      </transition>
    </div>

    <!-- 主体内容 -->
    <div class="side-pane-main" :style="{ marginLeft }">
      <div class="side-pane-main-header" v-if="$slots.mainHeader">
        <slot name="mainHeader"></slot>
      </div>

      <!-- 主体内容区 -->
      <div class="side-pane-main-body">
        <slot name="main"></slot>
      </div>

      <el-button v-if="fold" class="unfold-btn" type="text" icon="el-icon-arrow-right" @click="changeFold"></el-button>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    height: {
      type: String,
      default: '100%'
    },
    sideWidth: {
      type: String,
      default: '25%'
    }
  },
  computed: {
    marginLeft () {
      return this.fold ? 0 : this.sideWidth
    }
  },
  data () {
    return {
      fold: false,
    }
  },
  methods: {
    /**
     * @method changeFold 收起/展开侧边菜单
     */
    changeFold () {
      this.fold = !this.fold
    }
  },
}
</script>

样式

收起侧边时加上过渡动画,看起来会更自然~

<style lang="scss" scoped>
.side-pane {
  position: relative;
  min-height: 100px;
  border: 1px solid #d7dae2;
  background-color: #fff;

  &.fold {
    .side-pane-left {
      width: 0;
      height: 0;
      border: none;
    }
    .side-pane-main {
      margin-left: 0;
    }
    &:hover {
      .unfold-btn {
        visibility: visible;
      }
    }
  }

  .side-pane-left {
    overflow: hidden;
    position: absolute;
    height: 100%;
    top: 0;
    left: 0;
    border-right: 1px solid #d7dae2;
    transition: width 0.3s;

    &:hover {
      .fold-btn {
        visibility: visible;
      }
    }

    &-con {
      .side-pane-left-header {
        overflow: hidden;
        box-sizing: border-box;
        min-height: 40px;
        padding: 8px 20px 8px 16px;
        border-bottom: 1px solid #d7dae2;
      }

      .fold-btn {
        visibility: hidden;
        position: absolute;
        width: 20px;
        height: 40px;
        top: 0;
        right: 0;
        color: #666;
        border-radius: 0;
        background-color: rgba($color: #000000, $alpha: 0.05);
        &:hover {
          background-color: rgba($color: #000000, $alpha: 0.15);
        }
      }
    }
  }

  .side-pane-main {
    position: relative;
    transition: all 0.3s;

    .side-pane-main-header {
      box-sizing: border-box;
      min-height: 40px;
      padding: 8px 20px;
      border-bottom: 1px solid #d7dae2;
    }

    .side-pane-main-body {
      padding: 8px 20px;
    }

    .unfold-btn {
      visibility: hidden;
      position: absolute;
      width: 20px;
      height: 40px;
      top: 0;
      left: 0;
      color: #666;
      border-radius: 0;
      background-color: rgba($color: #000000, $alpha: 0.05);
      &:hover {
        background-color: rgba($color: #000000, $alpha: 0.15);
      }
    }
  }
}

.side-pane-left-enter-active,
.side-pane-left-leave-active {
  transition: opacity 0.5s;
}
.side-pane-left-enter,
.side-pane-left-leave-to {
  opacity: 0;
}
</style>

使用

代码

<template>
  <div class="component-side-pane">
    <side-pane side-width="20%">
      <span class="title" slot="leftHeader">文章列表</span>
      <div class="article-list" slot="left">
        <div class="article-item" v-for="i in 10" :key="i">这是文章 {{ i }}</div>
      </div>
      <span class="title" slot="mainHeader">文章标题</span>
      <div slot="main" class="content">
        这是文本内容
      </div>
    </side-pane>
  </div>
</template>

效果图

image.png

image.png

首次发文,小白请大家多多指教!