我之前写过,参考链接:https://juejin.im/post/684490...
<template>
<el-select
v-model="dataArr"
:multiple="multiple"
filterable
:placeholder="placeholder"
:disabled="disabled"
:collapse-tags="collapseTags"
@remove-tag="handleTagChange"
@change="handleTagChange"
@visible-change="handleOptionHidden"
:filter-method="handleSelectFilter"
class="hi-input">
<el-option value="0"
class="hidden">
</el-option>
<el-checkbox
v-if="selectAll"
v-model="checked"
@change="handleSelectAll"
class="select-all">
Select All
</el-checkbox>
<el-tree
ref="tree"
:data="options"
node-key="key"
show-checkbox
:default-checked-keys="selectedData"
@check="handleCheckChange"
:filter-node-method="handleTreeFilter"
:props="defaultProps">
</el-tree>
</el-select>
</div>
</template>
<script>
export default {
data() {
return {
dataArr: [],
selectedData: [],
selectedItem: [],
defaultProps: {
children: 'children',
label: 'label'
},
checked: false
};
},
props: {
dataList: {
type: Array,
default: function() {
return [];
}
},
options: {
type: Array,
default: function() {
return [];
}
},
placeholder: {
type: String,
default: 'Select'
},
selectAll: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
multiple: {
type: Boolean,
default: true
},
title: {
type: String
},
collapseTags: {
type: Boolean,
default: true
}
},
watch: {
selectedData: function(newValue) {
this.$nextTick(() => { this.dataArr = this.handleDataTransform(newValue, 'key', 'label'); });
},
dataList: {
immediate: true,
handler(newValue) {
this.selectedData = newValue;
this.$nextTick(() => this.$refs.tree && this.$refs.tree.setCheckedKeys(this.selectedData));
this.cancelSelectAll();
}
}
},
methods: {
handleSelectFilter: function(val) {
this.$refs.tree.filter(val);
},
handleTreeFilter: function(value, data) {
if (!value) return true;
return data.label.toUpperCase().indexOf(value.toUpperCase()) !== -1;
},
// 下拉框收起时再触发
handleOptionHidden: function(item) {
// 处理选中内容没变的情况
if (item) {
this.selectedItem = [...this.selectedData];
} else {
if (!this.$util.isEqual(this.selectedItem, this.selectedData)) {
this.handleUpdate(this.selectedData);
}
// 为了处理搜素关键字输入后,移出下拉框焦点后 options 恢复数据
this.$refs.tree.filter('');
}
},
handleTagChange: function() {
this.selectedData = this.handleDataTransform(this.dataArr, 'label', 'key');
this.$refs.tree.setCheckedKeys(this.selectedData);
this.handleUpdate(this.selectedData);
},
handleUpdate: function(item) {
this.$emit('update:dataList', item);
this.$emit('change-field');
this.cancelSelectAll();
},
handleCheckChange: function() {
this.selectedData = this.$refs.tree.getCheckedKeys().filter(_ => _);
// 这里是为了通过表单验证的处理
this.$emit('update:dataList', this.selectedData);
this.cancelSelectAll();
},
handleDataTransform: function(source, key, value) {
return this.options.map(_ => {
let arr = [];
if (_.children) {
arr = source.map(item => this.$business.getNameById(
_.children,
item,
key,
value
));
} else if (source.includes(_[key])) {
arr = [_[value]];
}
return arr.filter(item => item);
}).reduce((acc, cur) => {
return acc.concat(cur);
}, []);
},
cancelSelectAll() {
// 处理全选
if (this.selectAll && (this.selectedData.length !== this.options.length)) {
this.checked = false;
}
},
handleSelectAll() {
this.selectedData = this.checked ? this.options.map(_ => _.key) : [];
this.$refs.tree && this.$refs.tree.setCheckedKeys(this.selectedData);
}
}
};
</script>
<style lang="less" scoped>
</style>
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…