基于el-tree的自定义侧边菜单栏(手风琴)

话不多说,先上效果图:

主要思路:

  1、使用elementUI的插槽工具,分别对一级节点和叶节点进行展示

  2、对样式进行调整

主要代码(vue组件):

 

<template>
  <div class="tree-wrap">
    <el-tree
      ref="tree"
      :data="data"
      :props="defaultProps"
      :default-expanded-keys="expendIdArr"
      node-key="id"
      :indent="0"
      icon-class="mycons"
      :filter-node-method="filterNode"
    >
      <template slot-scope="{node, data}">
        <div
          v-if="node.level === 1"
          :class="['tree-header-panel',currentNodeParentId === data.id? 'tree-parent-active' : '', node.expanded ? 'border-bottom-line' : 'border-bottom-line']"
          @click="treeNodeClick(node, data)"
        >
          <p class="tree-header-p">
            <i class="gwlz-iconlaptop iconfont-class"></i>
            <span><b>{{node.label}}</b></span>
          </p>
          <i
            v-if="data.children && data.children.length > 0"
            :class="['iconfont','gwlz-iconangle-right', node.expanded ? 'rotate' : 'rotate1']"
          ></i>
        </div>
        <div
          v-else
          :class="['tree-content-panel',currentNodeId === data.id && node.isLeaf ? 'tree-active' : '', 'leaf-border-bottom-line']"
          @click="treeNodeClick(node, data)"
        >
          <div :style="{'padding-left': (node.level + 1) * 16 + 'px'}">
            <div v-if="data.children" class="tree-content-panel-span">
              <span>
                <i class="gwlz-iconapplication  iconfont-class"></i>
                <span>{{node.label}}</span>
              </span>
              <i :class="['iconfont','gwlz-iconangle-right', node.expanded ? 'rotate' : 'rotate1']"></i>
            </div>
            <div v-else class="tree-content-panel-span">
              <span>
                <i class="gwlz-iconapplication  iconfont-class"></i>
                <span>{{node.label}}</span>
              </span>
              <i style="width: 8px;height: 16px;display: inline-block;"></i>
            </div>
          </div>
        </div>
      </template>
    </el-tree>
  </div>
</template>

<script>
export default {
  name: 'LeftPanel',
  data () {
    return {
      currentNodeId: '',
      currentNodeParentId: '',
      expendIdArr: [],
      data: [{
        id: 1,
        label: '一级 1',
        children: [{
          id: 4,
          label: '二级 1-1'
        }, {
          id: 9,
          label: '二级 1-2'
        }, {
          id: 10,
          label: '二级 1-3'
        }
        ]
      }, {
        id: 2,
        label: '一级 2',
        children: [{
          id: 5,
          label: '二级 2-1'
        }, {
          id: 6,
          label: '二级 2-2'
        }]
      }, {
        label: '一级 3',
        id: 11,
        children: [{
          id: 12,
          label: '二级 3-1'
        }, {
          id: 13,
          label: '二级 3-2'
        }]
      }],
      defaultProps: {
        children: 'children',
        label: 'label'
      }
    }
  },
  mounted () {
    this.getFirstData(this.data)
    this.currentNodeParentId = this.data[0].id
  },
  methods: {
    getFirstData (data) {
      if (data && data.length > 0) {
        if (data[0].children && data[0].children.length > 0) {
          this.getFirstData(data[0].children)
        } else {
          this.expendIdArr.push(data[0].id)
          this.currentNodeId = data[0].id
        }
      }
    },
    filterNode (value, data) {
      if (!value) return true
      return data.name.indexOf(value) !== -1
    },
    treeNodeClick (node, data) {
      if (node.isLeaf) {
        this.currentNodeId = data.id
        this.getParentNodeId(node)
      }
    },
    getParentNodeId (node) {
      if (node) {
        if (node.level === 1) {
          this.currentNodeParentId = node.data.id
        } else {
          this.getParentNodeId(node.parent)
        }
      }
    }
  }
}
</script>

<style lang="scss" scoped>
  .tree-wrap {
    height: 100%;
    width: 300px;
    border-right: 1px solid #dcdfe6;
    overflow-y: auto;
    box-sizing: border-box;

    /deep/ .mycons {
      padding: 0;
    }

    /deep/ .el-tree {
      border-radius: 0;
      .el-tree-node:focus > .el-tree-node__content {
        background-color: #ffffff !important;
      }

      > .el-tree-node {
        & .is-current > .el-tree-node__content {
          background-color: #ffffff !important;
        }

        > .el-tree-node__content {
          width: 100%;
          height: auto;
          line-height: 54px;

          &:hover {
            background-color: rgba(220, 223, 230, 0.15);

            span, i {
              color: #409eff;
            }
          }
        }

        .el-tree-node__children {
          .el-tree-node__content {
            height: auto;
            line-height: 54px;

            &:hover {
              background-color: rgba(220, 223, 230, 0.15);

              span, i {
                color: #409eff;
              }
            }
          }
        }

        .tree-header-panel {
          display: flex;
          width: 100%;
          height: 100%;
          padding-left: 16px;
          justify-content: space-between;
          align-items: center;
          font-size: 18px;
        }

        .tree-content-panel {
          display: inline-block;
          width: 100%;
          height: auto;
          line-height: 54px;
        }

        .tree-active {
          font-weight: bold;
          position: relative;

          & span {
            color: #409eff;
          }
        }

        .tree-parent-active {
          color: #409eff;
          background: #f5f7fa;
          font-weight: bold;
          position: relative;

          &:before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 6px;
            height: 100%;
            background: #409eff;
          }
        }

        .tree-content-panel-span {
          display: flex;
          justify-content: space-between;
          align-items: center;
          font-size: 17px;
          & span{
            display: flex;
            justify-content: space-between;
            align-items: center;
          }
        }

        .border-line {
          border-top: 1px solid #dcdfe6;
          border-bottom: 1px solid #dcdfe6;
        }

        .border-bottom-line {
          border-bottom: 1px solid #dcdfe6;
        }

        .leaf-border-bottom-line {
          border-bottom: 1px dashed #dcdfe6;
        }

        .border-top-line {
          border-top: 1px solid #dcdfe6;
        }
      }

      .tree-header-p {
        display: flex;
        align-items: center;
        margin: 0;
      }
      .iconfont-class {
        font-size: 23px;
        margin-right: 15px;
      }

      .iconfont {
        margin-right: 16px;
        height: 20px;
        line-height: 20px;
      }

      .rotate {
        transform-origin: center center; //旋转中心要是正中间 才行
        transform: rotate(90deg);
        -webkit-transform: rotate(90deg);
        -moz-transform: rotate(90deg);
        -ms-transform: rotate(90deg);
        -o-transform: rotate(90deg);
        transition: transform 0.2s; //过度时间 可调
        -moz-transition: -moz-transform 0.2s;
        -moz-transition: -moz-transform 0.2s;
        -o-transition: -o-transform 0.2s;
        -ms-transition: -ms-transform 0.2s;
      }

      .rotate1 {
        transform-origin: center center;
        transform: rotate(0deg); //返回原点
        -webkit-transform: rotate(0deg);
        -moz-transform: rotate(0deg);
        -ms-transform: rotate(0deg);
        -o-transform: rotate(0deg);
        transition: transform 0.2s;
        -moz-transition: -moz-transform 0.2s;
        -moz-transition: -moz-transform 0.2s;
        -o-transition: -o-transform 0.2s;
        -ms-transition: -ms-transform 0.2s;
      }
    }
  }
</style>

 

 

-------------------------------------------------------------------------------------------------

 

QQ群:871934478

 

版权所有,转载请注明源地址                          

 

-------------------------------------------------------------------------------------------------

 

 

posted @ 2020-12-16 17:30  一两米  阅读(1483)  评论(0编辑  收藏  举报