主要的功能有:
1.全选
2.传入禁用的ID,把对应是数据禁用
子组件
<template>
<div>
<el-select
v-model="selectedArray"
v-bind="$attrs"
@change="changeSelect"
@remove-tag="removeTag"
>
<el-option
v-if="showSelectAll"
label="全选"
value="全选"
@click.native="selectAll"
/>
<el-option
v-for="(item, index) in options"
:key="index"
:label="item.label"
:value="item.value"
:disabled="item.disabled"
/>
</el-select>
</div>
</template>
<script>
import { cloneDeep } from '@mcfe/tools';
export default {
name: 'SelectAll',
props: {
// v-model绑定的值
value: {
type: [String, Number, Array],
default: '',
},
labelKey: {
type: [String, Function],
default: 'label',
},
valueKey: {
type: String,
default: 'value',
},
// 数据源
source: {
type: [Array, String],
default: () => ([]),
},
// 是否有全选功能
showSelectAll: {
type: Boolean,
default: false,
},
// 禁止的属性
disabledIds: {
type: Array,
default: () => ([]),
},
},
data() {
return {
selectedArray: [],
options: this.source,
isSelectAll: false, // 添加isSelectAll属性
};
},
watch: {
disabledIds: {
deep: true,
immediate: true,
handler() {
this.options = this.disabledList(this.options);
},
},
},
methods: {
// 点击全选时
selectAll() {
if (this.showSelectAll) {
// 如果isSelectAll为true,则清空selectedArray,实现取消全选
if (this.isSelectAll) {
this.selectedArray = [];
this.isSelectAll = false; // 设置isSelectAll为false
} else {
// 否则,将options中非禁止选择的value添加到selectedArray中,实现全选
this.selectedArray = this.options.filter(({ disabled }) => !disabled).map(({ value }) => value);
this.selectedArray.unshift('全选');
// 设置isSelectAll为true
this.isSelectAll = true;
}
}
this.$emit('input', this.selectedArray);
},
// 选中的值发生变化
changeSelect(val) {
if (this.showSelectAll) {
if (typeof val === 'number') {
console.warn('单选的时候就不要传showSelectAll了.');
return;
}
// 获取非禁止选择的数据的长度
const enabledOptionsLength = this.options.filter(({ disabled }) => !disabled).length;
// 如果选中的值不包括全选且选中值的长度和非禁止选择的数据的长度相等,证明这时候已经全选了,把全选追加到选中的数组中
if (!val.includes('全选') && val.length === enabledOptionsLength) {
this.selectedArray.unshift('全选');
} else if (val.includes('全选') && (val.length - 1) < enabledOptionsLength) {
// 当全选时,删除了一项数据
this.selectedArray = this.selectedArray.filter((item) => item !== '全选');
}
}
this.$emit('input', this.selectedArray);
},
// 全选的时候, 如果点击删除全选就把选中的数据清空
removeTag(val) {
if (this.showSelectAll && val === '全选') {
this.selectedArray = [];
}
this.$emit('input', this.selectedArray);
},
// 禁用列表
disabledList(list = []) {
const { disabledIds = [], labelKey, valueKey } = this;
// 使用 cloneDeep 深拷贝列表数据,避免修改原数据
// 使用 map 方法遍历列表数据,对每一项进行格式化处理
const stackList = cloneDeep(list).map((item) => {
const stack = {};
// 如果 disabledIds 存在,且为数组,且包含当前项的 valueKey,则将当前项的 disabled 属性设为 true
if (disabledIds && Array.isArray(disabledIds) && disabledIds.includes(item[valueKey])) {
stack.disabled = true;
}
// 根据 labelKey 的类型,如果是函数则调用函数获取 label,否则直接从 item 中获取 label
const label = (typeof labelKey === 'function') ? labelKey(item) : item[labelKey];
// 返回格式化后的当前项,包含 disabled,label,value 属性
return {
...stack,
label,
value: item[valueKey],
};
});
// 返回格式化后的列表数据
return stackList;
},
},
};
</script>
父组件
<my-select
v-model="poiIdList"
show-select-all
collapse-tags
clearable
filterable
:label-key="labelKey"
multiple
:disabled-ids="disabledIds"
:source="PayTypeEnum"
placeholder="请选择xxxx"
/>
// 要禁用的属性
disabledIds: [1],
// 自定义labelKey
labelKey(item) {
return `${item.label}[(${item.value})]`;
},
// 数据源
PayTypeEnum: [
{ label: '1转账', value: 1 },
{ label: '2支票', value: 2 },
{ label: '3转账', value: 3 },
{ label: '4支票', value: 4 },
{ label: '5转账', value: 5 },
{ label: '6支票', value: 6 },
{ label: '7转账', value: 7 },
{ label: '8支票', value: 8 },
{ label: '9转账', value: 9 },
{ label: '10支票', value: 10 },
{ label: '11转账', value: 11 },
]