vue自定义树形选择

1.树引用组件

<template>
  <div class="h100 treeLeft radius5 hidden">
    <div class="treeLeftDom relative paddingB20 h100 w100">
      <div class="absolute w100 treeTop flex justify-between items-center">
        <el-avatar :size="30" icon="icon iconfont icon-xiangqing"></el-avatar>
        <span class="enterpriseTitle">{{enterprise.name}}</span>
        <div class="paddingR5 operationBtn flex items-center">
          <i class="el-icon-arrow-down cursor"></i>
        </div>
      </div>
      <div class="paddingT10 w100 h100 overflow">
        <TreeA v-for="node in treeData" :selectId="selectId" @change="nodeChange" :level="-1" :key="node.id"
               :node="node"/>
      </div>
    </div>
  </div>
</template>

<script>
  import TreeA from "./TreeA";
  export default {
    name: "OrgStructureLeft",
    components: {TreeA},
    data() {
      return {
        isOpenTree: true,
        treeData: [],
        selectId: '3c58d359a90b46ee83f0113b7f4cd811',
        enterprise: {id: '', name: '', parentId: ''},
        defaultProps: {
          children: 'childDepartment',
          label: 'name'
        }
      }
    },
    computed: {
      ...mapState(['currentEnterprise'])
    },
    methods: {
      departmentsTree() {
        this.httpClient.get(this.baseInfo.departmentsTree, {}, ({childDepartment, id, name, parentId}) => {
          this.enterprise = {childDepartment, id, name, parentId};
          this.treeData = childDepartment || [];
          this.sessionSave.save('departmentTree',this.enterprise);
          if(childDepartment&&childDepartment.length){
            this.$emit('nodeChange',{...childDepartment[0]})
          }
        })
      },
      /**
       * 节点点击事件
       * @param id 部门ID
       * @param name 部门名称
       */
      nodeChange({id,name}) {
        this.selectId = id;
        this.$emit('nodeChange',{id,name})
      }
    },
    mounted() {
      this.departmentsTree()
    },
    watch: {
      currentEnterprise: 'departmentsTree'
    }
  }
</script>

<style scoped>
  .treeLeftDom {
    padding-top: 30px;
  }

  .treeLeft {
    padding: 10px 4px;
    float: left;
    width: 280px;
    background-color: #F8F8F8;
  }

  .title {
    padding: 0 4px;
    width: 28rem;
    font-size: 14px;
  }

  .treeTop {
    top: 0;
    left: 0;
    padding: 0 50px;
    height: 30px;
    background-color: #F8F8F8;
  }

  .el-avatar {
    position: absolute;
    top: 0;
    left: 10px;
  }

  .enterpriseTitle {
    line-height: 30px;
  }

  .operationBtn {
    position: absolute;
    height: 30px;
    top: 0;
    right: 0;
  }
</style>

2.编写组件

<template>
  <div>
    <div :class="'paddingV10 cursor '+(selectId===node.id?'isSelect':'noSelect')"
         :style="{paddingLeft:(50+levelNum*20)+'px'}">
      <div class="relative paddingL30 optionBtn">
        <i class="absolute circle marginR20"></i>
        <div class="over-text-row w100" @click="$emit('change',node)">{{node.name}}</div>
        <div class="paddingL10 optionBtnDom absolute flex justify-end items-center">
          <i v-show="isHave" :class="'el-icon-arrow-'+(nodeShow?'down':'up')" @click="nodeShow=!nodeShow"></i>
          <i class="el-icon-plus"></i>
          <i class="icon iconfont icon-icon_edit"></i>
          <i class="icon iconfont icon-shanchu"></i>
        </div>
      </div>
    </div>
    <TreeA v-show="nodeShow" v-for="item in node.childDepartment" :selectId="selectId" :level="levelNum" :key="item.id"
           :node="item" @change="nodeId=>($emit('change',nodeId))"/>
  </div>
</template>

<script>
  export default {
    name: "TreeA",
    props: ['node', 'level', 'selectId'],
    computed:{
      isHave:function () {
        if(!this.node.childDepartment){
          return false
        }
        return this.node.childDepartment.length>0
      }
    },
    data() {
      return {
        levelNum: 0,
        nodeShow: true
      }
    },
    mounted() {
      this.levelNum = this.level + 1
    }
  }
</script>

<style scoped lang="scss">
  .isSelect {
    .circle {
      border: 1px solid #007AFF;
    }
    .over-text-row, .el-icon-arrow-down, .circle {
      color: #007AFF;
    }
  }

  .noSelect {
    .circle {
      border: 1px solid #101010;
    }
    .over-text-row, .circle {
      color: #101010;
    }
  }

  .circle {
    content: '';
    top: 8px;
    left: 5px;
    display: block;
    width: 8px;
    height: 8px;
    -webkit-border-radius: 4px;
    -moz-border-radius: 4px;
    border-radius: 4px;
  }

  .optionBtn {
    padding-right: 25px;
  }

  .optionBtnDom {
    top: 0;
    right: 0;
    padding-right: 5px;
  }

  .icon-icon_edit, .icon-shanchu {
    font-size: 14px;
  }

  .icon-icon_edit, .icon-shanchu, .el-icon-plus {
    display: none;
  }

  .optionBtn:hover {
    .icon-icon_edit, .icon-shanchu, .el-icon-plus {
      display: inline-block;
    }
    .optionBtnDom {
      width: 100px;
    }
    padding-right: 100px;
  }
  .optionBtnDom>i+i{
    margin-left: 5px;
  }
</style>

 

3.显示效果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值