vue element-ui 组织结构多选框组件,树形复选框.支持多选

组件地址https://www.vue-treeselect.cn/#more-features

效果

在这里插入图片描述
在这里插入图片描述

vue代码

标签

<div class="app-container" @click="divClick">
	<el-form>
      <el-form-item>
        <tree-select ref="treeSelect"
                     :data="officeTreeList"
                     :defaultProps="defaultProps"
                     @parent-event="popoverHide"
                     multiple
                     :checkStrictly="false"
                     :clear="clearTreeSelect"
                     :nodeKey="nodeKey"
                     :checkedKeys="defaultCheckedKeys"
                     @popoverHide="popoverHide">
        </tree-select>
      </el-form-item>
   </form>
</div>

import
TreeSelect文件在后面

  import TreeSelect from '@/components/TreeSelect';

components

    components: {
      TreeSelect,
    },

created

    created() {
      this.getTree();
    },

data

      return {
        //下拉树
        isShowSelect: false,//选择面板,默认隐藏
        officeTreeList: [],//树形结构数据
        selectedOfficeIds: '',//选择后返回的选中id,以逗号拼接
        selectedOffices: [],//选择后返回的选中对象,
        clearTreeSelect: 0,
        defaultProps: {
          children: "children",//树形结构数据中对应的属性名称,可改为自己数据中属性
          label: "label"//树形结构数据中对应的属性名称,可改为自己数据中属性
        },
        nodeKey: "id",//树形结构数据中对应的属性名称,可改为自己数据中属性
        defaultCheckedKeys: [],//默认初次选中的数据
        }

mounted

// this.defaultCheckedKeys.push('o60');//默认选中楚留香传奇
      this.$nextTick(() => {
        this.$refs.treeSelect.loadCheckedKeys();
      })
      // this.selectedOfficeIds = ['o60'];//第一次手动放进去,以后就直接用这个变量即可

methods

      popoverHide(checkedIds, checkedData) {
         this.selectedOfficeIds = checkedIds;
        // this.selectedOffices = checkedData;//此数据没大用,可注释
        // if (checkedData != undefined && checkedData != null) {
        //   checkedData.forEach(item => {
        //     if (item.children == undefined || item.children == null) {
        //       this.selectedOffices.push(item.id);
        //     }
        //   });
        // }
      },
      /** 点击空白隐藏 */
      divClick() {
        this.$nextTick(() => {
          this.$refs.treeSelect.changeIsShowSelect();
        })
      },
      /** TODO 组织树 */
      getTree() {
        treeselectMat().then(res => {
          this.officeTreeList = res.data[0].children; //换自己的
        })
      },
            /** 重置按钮操作 */
      resetQuery() {
        // 子组件监听到数据的变化后会将子组件中的数据清空
        this.clearTreeSelect = this.clearTreeSelect + 1;
      },

TreeSelect

<!--
    /**
     * 下拉选择树形组件,下拉框展示树形结构,提供选择某节点功能,方便其他模块调用
     * @date 2020-12-09
     * 调用示例:
     * <tree-select :height="400" // 下拉框中树形高度
     *              :width="200" // 下拉框中树形宽度
     *              :data="data" // 树结构的数据
     *              :defaultProps="defaultProps" // 树结构的props
     *              multiple   // 多选
     *              :rootNodeChick="true" // 是否可以选择根节点。默认 false ture 为可选。false 为不可选
     *              checkStrictly // 多选时,严格遵循父子不互相关联
     *              :nodeKey="nodeKey"   // 绑定nodeKey,默认绑定'id'
     *              :checkedKeys="defaultCheckedKeys"  // 传递默认选中的节点key组成的数组
     *              @popoverHide="popoverHide"> // 事件有两个参数:第一个是所有选中的节点ID,第二个是所有选中的节点数据
     *              </tree-select>
     *
     * import TreeSelect from "@/utils/components/tree-select.vue";
     * components: { TreeSelect },
     *
     *数据格式
     *let obj = {
                "id": "10",
                "label": "琼瑶作品集",
                "children": [],
                  };
     * 清空树的选中状态。只需要将clear 从 0 累加就可以。这里是监听的数据改变状态。不为 0 则清空数据。Number类型
     */
-->
<template>
  <div style="width:284px;display: inline-block;margin-left: -5px">
    <!-- <div class="mask"
         v-show="isShowSelect"
         @click="isShowSelect = !isShowSelect"></div> -->
    <el-popover placement="bottom-start"
                :width="width"
                trigger="manual"
                v-model="isShowSelect"
                @hide="popoverHide"
                clearable>
      <el-tree class="common-tree"
               :style="style"
               clearable
               ref="tree"
               :data="data"
               :props="defaultProps"
               :show-checkbox="multiple"
               :node-key="nodeKey"
               :check-strictly="checkStrictly"
               :default-expand-all='false'
               :expand-on-click-node="false"
               :default-checked-keys="defaultCheckedKeys"
               :highlight-current="true"
               @node-click="handleNodeClick"
               @check-change="handleCheckChange"></el-tree>
      <el-select :style="selectStyle"
                 slot="reference"
                 ref="select"
                 placeholder="请选择单位(可多选)"
                 v-model="selectedData"
                 :multiple="multiple"
                 collapse-tags
                 clearable
                 @click.native="isShowSelect = !isShowSelect"
                 class="tree-select">
        <el-option v-for="item in options"
                   :key="item.value"
                   :label="item.label"
                   :value="item.value"></el-option>
      </el-select>
    </el-popover>
  </div>
</template>

<script>
  export default {
    name: "tree-select",
    // props: ["clear"],
    props: {
      // 树结构数据
      data: {
        type: Array,
        default () {
          return [];
        }
      },
      // 是否可选根节点
      rootNodeChick: Boolean,
      // 是否清空数据
      clear: Number,
      defaultProps: {
        type: Object,
        default () {
          return {};
        }
      },
      // 配置是否可多选
      multiple: {
        type: Boolean,
        default () {
          return false;
        }
      },
      nodeKey: {
        type: String,
        default () {
          return "id";
        }
      },
      // 显示复选框情况下,是否严格遵循父子不互相关联
      checkStrictly: {
        type: Boolean,
        default () {
          return true;
        }
      },
      // 默认选中的节点key数组
      checkedKeys: {
        type: Array,
        default () {
          return [];
        }
      },
      width: {
        type: Number,
        default () {
          return 260;
        }
      },
      height: {
        type: Number,
        default () {
          return 360;
        }
      },
    },
    data () {
      return {
        defaultCheckedKeys: [],
        isShowSelect: false, // 是否显示树状选择器
        options: [],
        selectedData: [], // 选中的节点
        style: "width:" + this.width + "px;" + "height:" + this.height + "px;",
        selectStyle: "width:" + (this.width + 24) + "px;",
        checkedIds: [],
        checkedData: []
      };
    },
    mounted () {
      if (this.checkedKeys.length > 0) {
        if (this.multiple) {
          this.defaultCheckedKeys = this.checkedKeys;
          this.selectedData = this.checkedKeys.map(item => {
            var node = this.$refs.tree.getNode(item);
            return node.label;
          });
        } else {
          var item = this.checkedKeys[0];
          this.$refs.tree.setCurrentKey(item);
          var node = this.$refs.tree.getNode(item);
          this.selectedData = node.label;
        }
      }
    },
    methods: {
      loadCheckedKeys () {
        if (this.checkedKeys.length > 0) {
          if (this.multiple) {
            this.defaultCheckedKeys = this.checkedKeys;
            this.selectedData = this.checkedKeys.map(item => {
              var node = this.$refs.tree.getNode(item);
              return node.label;
            });
          } else {
            var item = this.checkedKeys[0];
            this.$refs.tree.setCurrentKey(item);
            var node = this.$refs.tree.getNode(item);
            this.selectedData = node.label;
          }
        }
      },
      changeIsShowSelect () {
        this.isShowSelect = false;
      },
      popoverHide () {
        if (this.multiple) {
          this.checkedIds = this.$refs.tree.getCheckedKeys(); // 所有被选中的节点的 key 所组成的数组数据
          this.checkedData = this.$refs.tree.getCheckedNodes(); // 所有被选中的节点所组成的数组数据
        } else {
          this.checkedIds = this.$refs.tree.getCurrentKey();
          this.checkedData = this.$refs.tree.getCurrentNode();
        }
        this.$emit("popoverHide", this.checkedIds, this.checkedData);
      },
      // 节点被点击时的回调,返回被点击的节点数据
      handleNodeClick (data, node) {
        if (!this.multiple) {
          let tmpMap = {};
          tmpMap.value = node.key;
          tmpMap.label = node.label;
          this.options = [];
          this.options.push(tmpMap);
          this.selectedData = node.label;
          this.isShowSelect = !this.isShowSelect;
        }
      },
      // 节点选中状态发生变化时的回调
      handleCheckChange () {
        var checkedKeys = this.$refs.tree.getCheckedKeys(); // 所有被选中的节点的 key 所组成的数组数据
        this.options = [];
        if (!this.rootNodeChick)
          checkedKeys.forEach(item => {
            var node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node
            let tmpMap = {};
            if (node.childNodes.length == 0) {
              tmpMap.value = node.key;
              tmpMap.label = node.label;
              this.options.push(tmpMap);
            }
          });
        else
          this.options = checkedKeys.map(item => {
            var node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node
            let tmpMap = {};
            tmpMap.value = node.key;
            tmpMap.label = node.label;
            return tmpMap;
          });
        this.selectedData = this.options.map(item => {
          return item.label;
        });
      }
    },
    watch: {
      isShowSelect (val) {
        // 隐藏select自带的下拉框
        this.$refs.select.blur();
      },
      clear: function (n, o) {
        //箭头函数  不然会发生this改变
        if (n != 0) {
          this.selectedData = [];
          this.$nextTick(() => {
            this.$refs.tree.setCheckedKeys([]);
          });
        }
      },
      selectedData: function (newData, oldData) {
        this.popoverHide();
        if (
          newData == undefined ||
          newData == null ||
          newData == [] ||
          newData.length == 0
        )
          this.$refs.tree.setCheckedKeys([]);
      }
    }
  };
</script>

<style scoped>
  .mask {
    width: 100%;
    height: 100%;
    position: fixed;
    top: 0;
    left: 0;
    opacity: 0;
    z-index: 999;
  }
  .common-tree {
    overflow: auto;
  }
</style>

<style>
  .tree-select .el-select__tags .el-tag .el-tag__close {
    display: none;
  }
  .tree-select .el-select__tags .el-tag .el-icon-close {
    display: none;
  }
</style>

感谢 https://blog.csdn.net/qq_15023917/article/details/110928005

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Vue Element-UI树形Table组件可以通过设置show-checkbox属性来显示复选框,但是默认情况下只会在非叶子节点上显示复选框,如果需要在最后一层也显示复选框,可以通过以下两种方式实现: 1. 使用slot-scope自定义单元格内容 在template使用slot-scope自定义单元格内容,通过判断当前行是否为最后一层来显示复选框。 ```html <el-table :data="data" style="width: 100%"> <el-table-column type="selection" width="55"></el-table-column> <el-table-column prop="name" label="名称"></el-table-column> <el-table-column label="操作"> <template slot-scope="{ row }"> <el-checkbox v-if="isLastLevel(row)" v-model="checkedNodes" :label="row.id"></el-checkbox> </template> </el-table-column> </el-table> ``` 在methods定义isLastLevel方法来判断当前行是否为最后一层: ```javascript methods: { isLastLevel(row) { return !row.children || row.children.length === 0; } } ``` 2. 使用tree-node-key属性指定叶子节点的key值 在使用树形数据时,可以通过tree-node-key属性指定叶子节点的key值,然后在show-checkbox属性使用leaf-only来显示所有叶子节点的复选框。 ```html <el-table :data="data" :tree-props="{children: 'children', hasChildren: 'hasChildren', id: 'id', label: 'name', key: 'id'}" :tree-node-key="'id'" :show-checkbox="true" :leaf-only="true" style="width: 100%"> <el-table-column prop="name" label="名称"></el-table-column> <el-table-column label="操作"> <template slot-scope="{ row }"> <el-checkbox v-model="checkedNodes" :label="row.id"></el-checkbox> </template> </el-table-column> </el-table> ``` 在这种方式下,只需要在template直接显示复选框即可,不需要判断当前行是否为最后一层。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诸葛延昌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值