组件地址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

Logo

前往低代码交流专区

更多推荐