封装elementUI-树组件

18 篇文章 1 订阅

本文只给出子组件的源代码,可以来我的主页看我封装的其他组件。
封装树组件,父子级不关联,并为树组件添加右键功能。

<template>
<div>
  <el-tree 
    :data="data" 
    :props='props'
    :highlight-current='highlight_current'
    :expand-on-click-node="expand_on_click_node"
    :default-expanded-keys='default_expanded_keys'
    :filter-node-method="filterNodeMethod"
    :node-key="node_key"
    @node-click="nodeClick"
    :ref="tree_ref"
    :show-checkbox='show_checkbox'
    :check-strictly='check_strictly'
    :default-expand-all='default_expand_all'
    :default-checked-keys='default_checked_keys'
    @check='check'
    @node-contextmenu="nodeContextmenu"
  ></el-tree>
  <div class='rightMenu' @mouseleave="rightNav=false" ref="rightNav" v-show="rightNav">
    <div @click="checkAll">勾选全部</div>
    <div @click="checkAllCancel">取消全部</div>
    <div @click="checkSelfOrChild">勾选本级及下级</div>
    <div @click="checkSelfOrChildCancel">取消本级及下级</div>
  </div>
</div>
</template>

<script>
  export default {
    name: 'tree',
    data () {
      return {
        rightNav:false,//控制右键菜单显示与隐藏
      }
    },
    props:{
      data:{//展示数据,必传,数组格式。
        type:Array,
        require:true,
        default(){
          return []
        }
      },
      props:{//配置选项,必传,对象格式。
        type:Object,
        require:true,
        default(){
          return {
          label: '',
          value: '',
          children: '',
          disabledRightMenu: false,//控制右键菜单是否启用,默认启用
          }
        }
      },
      tree_ref:{//相当于整颗树的ID,字符串类型,非必传。
        type:String,
        require:false,
        default:'tree'
      },
      expand_on_click_node:{//是否在点击节点的时候展开或者收缩节点, 默认值为 true,如果为 false,则只有点箭头图标的时候才会展开或者收缩节点。
        type:Boolean,
        require:false,
        default:true
      },
      highlight_current:{//是否高亮当前选中节点,默认值是 true。
        type:Boolean,
        require:false,
        default:true
      },
      default_expanded_keys:{//默认展开的节点的 key 的数组,数组格式。
        type:Array,
        require:false,
        default(){
          return []
        }
      },
      default_checked_keys:{//默认勾选的节点的 key 的数组,数组格式。
        type:Array,
        require:false,
        default(){
          return []
        }
      },
      node_key:{//每个树节点用来作为唯一标识的属性,整棵树应该是唯一的。
        type:String,
        require:false,
        default:null
      },
      show_checkbox:{//节点是否可被选择,即是否显示多选框,默认不显示多选框。
        type:Boolean,
        require:false,
        default:false
      },
      check_strictly:{//在显示复选框的情况下,是否严格的遵循父子不互相关联的做法,默认为 false。
        type:Boolean,
        require:false,
        default:false
      },
      default_expand_all:{//是否默认展开所有节点,默认为 false。
        type:Boolean,
        require:false,
        default:false
      },
      
    },
    methods:{

      /* 节点被点击时触发 */
      nodeClick(val) {
        console.log('nodeClick',val)
        //触发父组件事件
        this.$emit('node-click',val);//父组件事件名@node-click
      },

      /* 对树节点进行筛选时执行的方法,返回 true 表示这个节点可以显示,返回 false 则表示这个节点会被隐藏。 */
      filterNodeMethod(value, data, node){
        if (!value) return true;
        return data[this.props.label].includes(value);
      },

      /* 把树的ref传给父组件 */
      getTreeRef(){
        console.log('getTreeRef',this.tree_ref,this.$refs[this.tree_ref])
        //在勾选树的多选框时有用,在父组件中利用子组件的ref获取勾选后的node-key数组。
        this.$emit('get-tree-ref',this.$refs[this.tree_ref])//父组件事件名:get-tree-ref
      },

      /* 当复选框被点击的时候触发 */
      check(node,obj){
        // 共两个参数,依次为:传递给 data 属性的数组中该节点所对应的对象、树目前的选中状态对象,包含 checkedNodes、checkedKeys、halfCheckedNodes、halfCheckedKeys 四个属性
        console.log('check',node,obj)
        this.$emit('check',node,obj)//父组件事件名:check
      },

      /* 当单击鼠标右键时触发 */
      nodeContextmenu(event,obj,node,self){
        //如果没有多选框 或 禁用右键菜单
        if(!this.show_checkbox||this.props.disabledRightMenu){
          return;//右键不显示菜单。
        }
        //共四个参数,依次为:event、传递给 data 属性的数组中该节点所对应的对象、节点对应的 Node、节点组件本身。
        this.$emit('node-contextmenu',event,obj,node,self)//右键时触发父组件事件@right-menu-data,获取值
        this.nodeContextmenuObj = obj;
        var ev = ev || event;
        var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
        this.rightNav = true;
        this.$refs.rightNav.style.left = ev.clientX + "px";
        //当滑动滚动条时也能准确获取菜单位置
        this.$refs.rightNav.style.top = ev.clientY + scrollTop + "px";
      },
      //右键勾选递归
      getTreeCheck(dataAll,data,childrenName,code){
        if(data && data.length > 0){
          for(let i=0; i<data.length; i++){
            if(this.checkedKeys.indexOf(data[i][code]) === -1){
              this.checkedKeys.push(data[i][code]);
            }
            if(data[i][childrenName] && data[i][childrenName].length > 0){
              this.getTreeCheck(dataAll,data[i][childrenName],childrenName,code);
            }
            this.$refs[this.tree_ref].setCheckedKeys(this.checkedKeys);
          }
        }
      },
      //右键取消勾选递归
      getTreeCheckCancel(dataAll,data,childrenName,code){
        if(data && data.length > 0){
          for(let i=0; i<data.length; i++){
            if(this.checkedKeys.indexOf(data[i][code]) > -1){
              this.checkedKeys.splice(this.checkedKeys.indexOf(data[i][code]),1);
            }
            if(data[i][childrenName] && data[i][childrenName].length > 0){
              this.getTreeCheckCancel(dataAll,data[i][childrenName],childrenName,code);
            }
            this.$refs[this.tree_ref].setCheckedKeys(this.checkedKeys);
          }
        }
      },
      //勾选所有
      checkAll(){
        //判断是数组类型
        this.checkedKeys = [];
        this.getTreeCheck(this.data,this.data,this.props.children,this.node_key);
        //把勾选树的node-key返给父组件
        this.$emit('get-check-data',this.$refs[this.tree_ref].getCheckedKeys(),this.tree_ref)//触发父组件事件@get-check-data 
        this.rightNav = false;
        window.event.stopPropagation();
      },
      //勾选本级及下集
      checkSelfOrChild(){
        this.checkedKeys = this.$refs[this.tree_ref].getCheckedKeys();
        if(this.checkedKeys.indexOf(this.nodeContextmenuObj[this.node_key]) === -1){
          this.checkedKeys.push(this.nodeContextmenuObj[this.node_key]);
        }
        this.getTreeCheck(this.data,this.nodeContextmenuObj[this.props.children],this.props.children,this.node_key);
        this.$emit('get-check-data',this.$refs[this.tree_ref].getCheckedKeys(),this.tree_ref)//触发父组件事件@get-check-data 
        this.rightNav = false;
        window.event.stopPropagation();
      },
      //取消勾选所有
      checkAllCancel(){
        this.checkedKeys = [];
        this.$refs[this.tree_ref].setCheckedKeys(this.checkedKeys);
        //把勾选树的node-key返给父组件--未勾选所以是空数组
        this.$emit('get-check-data',this.$refs[this.tree_ref].getCheckedKeys(),this.tree_ref)//触发父组件事件@get-check-data
        this.rightNav = false;
        window.event.stopPropagation();
      },
      //取消勾选本级及下级
      checkSelfOrChildCancel(){
        this.checkedKeys = this.$refs[this.tree_ref].getCheckedKeys();
        if(this.checkedKeys.indexOf(this.nodeContextmenuObj[this.node_key]) > -1){
          this.checkedKeys.splice(this.checkedKeys.indexOf(this.nodeContextmenuObj[this.node_key]),1);
        }
        this.getTreeCheckCancel(this.data,this.nodeContextmenuObj[this.props.children],this.props.children,this.node_key);
        this.$emit('get-check-data',this.$refs[this.tree_ref].getCheckedKeys(),this.tree_ref)//触发父组件事件@get-check-data 
        this.rightNav = false;
        window.event.stopPropagation();
      },
    },
    created(){
    },
    mounted(){
      this.getTreeRef()
    }
  }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
  /*右键菜单*/  
  .rightMenu {
    position: fixed;
    left:0;
    top: 0;
    background: #fff;
    border: 1px solid #a9a9a9;
    z-index: 9999;
    padding-top: 2px;
    padding-bottom: 2px;
    font-size: 12px;
    color: #2c3e50!important;
  }
  .rightMenu div {
    cursor: pointer;
    height:24px;
    line-height: 24px;
    padding: 0 80px 0 20px;
  }
  .rightMenu div:hover {
    background: #eee!important;
    color: #2c3e50!important;
  }
</style>

效果:
在这里插入图片描述

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值