vue根据element-ui实现下拉多选

发布时间 2023-06-26 09:34:30作者: 九折丶水平

下拉多选element-ui

实现效果

组件代码

<template>
  <el-select
    class="maxwidth"
    v-model="showVal"
    multiple
    placeholder="请选择"
    :popper-append-to-body="false"
    @remove-tag="removetag"
    @clear="clearall"
    clearable
  >
    <el-option :value="selectTree" disabled>
      <el-tree
        :data="list"
        :props="props"
        ref="tree"
        check-strictly
        :expand-on-click-node="false"
        :node-key="props.id"
        check-on-click-node
        show-checkbox
        :default-checked-keys="value"
        @check-change="handleNodeClick"
      ></el-tree>
    </el-option>
  </el-select>
</template>
<script>
export default {
  name: "SelectTreeMultiple",
  props: {
    // 跟  this.$emit("input", []); 一起使用用来实现v-model
    value: {
      type: Array,
      default: () => {
        return [];
      },
    },
    // 树配置
    props: {
      type: Object,
      default: () => {
        return { children: "children", label: "label", id: "id" };
      },
    },
    // 下拉列表内容
    list: {
      type: Array,
      default: () => {
        return [];
      },
    },
    // 仅叶节点可选中
    onlyLeaf: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      selectTree: [], // 选中的数据
      showVal: [], //输入框展示
    };
  },
  watch: {
    value: {
      immediate: true,
      handler(val) {
        // 回显数据
        this.$nextTick(() => {
          this.echo(val);
        });
      },
    },
  },
  methods: {
    //回显数据
    echo(val) {
      // 禁止出现 this.$emit("input", []);
      if (!val.length) {
        this.$refs.tree.setCheckedNodes([]);
      }
      let datalist = this.$refs.tree.getCheckedNodes();
      this.selectTree = []; //置空
      this.showVal = [];
      datalist.forEach((item) => {
        this.selectTree.push(item[this.props.id]);
        this.showVal.push(item[this.props.label]);
      });
    },
    //节点点击事件
    handleNodeClick(data, self, child) {
      if (!data.children || !this.onlyLeaf) {
        let datalist = this.$refs.tree.getCheckedNodes();
        this.selectTree = []; //置空
        this.showVal = [];
        datalist.forEach((item) => {
          this.selectTree.push(item[this.props.id]);
          this.showVal.push(item[this.props.label]);
        });
        this.$emit("input", this.selectTree);
      } else {
        this.$refs.tree.setChecked(data[this.props.id], false);
      }
    },
    //单个节点移除
    removetag() {
      this.selectTree.splice(0, 1);
      let setlist = this.$refs.tree.getCheckedNodes();
      setlist.splice(0, 1);
      this.$nextTick(() => {
        this.$refs.tree.setCheckedNodes(setlist);
      });
    },
    //清除所有节点
    clearall() {
      this.selectTree = [];
      this.$nextTick(() => {
        this.$refs.tree.setCheckedNodes([]);
        this.$emit("input", []);
      });
    },
  },
};
</script>
<style scoped>
.el-scrollbar .el-scrollbar__view .el-select-dropdown__item {
  height: auto;
  max-height: 300px;
  padding: 0;
  overflow: hidden;
  overflow-y: auto;
}
.el-select-dropdown__item.selected {
  font-weight: normal;
}
ul li >>> .el-tree .el-tree-node__content {
  height: auto;
  padding: 0 20px;
}
.el-tree-node__label {
  font-weight: normal;
}
.el-tree >>> .is-current .el-tree-node__label {
  color: #409eff;
  font-weight: 700;
}
.el-tree >>> .is-current .el-tree-node__children .el-tree-node__label {
  color: #606266;
  font-weight: normal;
}
.maxwidth {
  width: 100%;
}
</style>

使用代码

<select-tree-multiple :props="tagProps" :list="tagsNameList2" v-model="tagType" ref="tag"></select-tree-multiple>