treeSelect 插件的简单封装

4 阅读1分钟

treeSelect 插件的简单封装

<template>
  <div class="container">
    <el-select
      v-model="selectTreeArr"
      placeholder="请选择"
      :popper-append-to-body="false"
      multiple
      clearable
      collapse-tags
      @remove-tag="removeTag"
      @clear="clearAll"
    >
      <el-option v-if="treeData.length !== 0" value="" style="display: none" />
      <el-tree
        ref="treeRef"
        :data="treeData"
        default-expand-all
        show-checkbox
        :node-key="nodeKey"
        highlight-current
        :filter-node-method="filterNode"
        :props="defaultProps"
        :default-checked-keys="value"
        @check-change="handleCheckChange"
      />
    </el-select>
  </div>
</template>
<script>
export default {
  name: 'TreeSelect',
  props: {
    value: { type: Array, default: () => [5, 6] },
    api: { type: Promise, default: ()=> {}},
    data: {
      type: Array,
      default: () => [
        {
          id: 1,
          label: '一级 1',
          children: [
            {
              id: 5,
              label: '一级 1-1',
            },
          ],
        },
        {
          id: 2,
          label: '二级 2',
          children: [
            {
              id: 6,
              label: '二级 2-1',
            },
            {
              id: 7,
              label: '二级 2-2',
            },
          ],
        },
        {
          id: 3,
          label: '三级 3',
          children: [
            {
              id: 8,
              label: '三级 3-1',
            },
            {
              id: 9,
              label: '三级 3-2',
              children: [
                {
                  id: 91,
                  label: '三级 3-2-1',
                },
                {
                  id: 92,
                  label: '三级 3-2-2',
                },
              ],
            },
          ],
        },
        {
          id: 4,
          label: '四级 1',
          children: [],
        },
      ],
    },
    nodeKey: { type: String, default: 'id' },
  },
  emits: ['update:value'],
  data() {
    return {
      // select 展示的文字
      selectTreeArr: [],
      // tree checked nodes
      selectTreeValue: [],
      // tree checked ids
      selectTreeIds: [],
      // tree search
      filterText: '',
      // tree props
      defaultProps: {
        children: 'children',
        label: 'label',
      },
      treeData: [],
    };
  },
  watch: {
    filterText(val) {
      this.$refs.treeRef.filter(val);
    },
  },
  mounted(){
    this.initData();
  },
  methods: {
    async initData(){
      try {
        const result = await this.api();
        this.treeData = result.data;
      } catch (e) {
        // console.error(e)
        this.treeData = this.data;
      }

      this.handleCheckChange();
    },
    // 过滤节点
    filterNode(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    }, // 移除Tag
    removeTag() {
      this.selectTreeValue.splice(0, 1);
      let setList = this.$refs.treeRef.getCheckedNodes();
      setList.splice(0, 1);
      this.$nextTick(() => {
        this.$refs.treeRef.setCheckedNodes(setList);
      });
    }, // 全部删除
    clearAll() {
      this.selectTreeValue = [];
      this.selectTreeArr = [];
      this.$nextTick(() => {
        this.$refs.treeRef.setCheckedNodes([]);
      });
    },
    handleCheckChange() {
      // getCheckedNodes方法接收两个 boolean 类型的参数: 1. 是否只是叶子节点,默认值为 false 2. 是否包含半选节点,默认值为 false
      this.$nextTick(() => {
        let dataList = this.$refs.treeRef && this.$refs.treeRef.getCheckedNodes(true);
        this.selectTreeValue = [];
        this.selectTreeArr = [];
        this.selectTreeIds = [];
        dataList.forEach((item) => {
          this.selectTreeValue.push({ id: item.id, label: item.label });
          this.selectTreeArr.push(item.label);
          this.selectTreeIds.push(item[this.nodeKey]);
        });

        this.$emit('update:value', this.selectTreeIds);
        this.$emit('input', this.selectTreeIds);
      });
    },
  },
};
</script>

<!-- <style lang="scss" scoped>
.setstyle {
  height: auto;
  padding: 0 !important;
  .setinput {
    padding: 6px;
  }
}
</style> -->