1.需求
Select 选择器 多选需要增加 全选 和 取消全选 功能,前端框架为vue2,UI组件为elementUI。
2. 代码
- html部分
<template>
<el-tooltip effect="dark"
:disabled="defaultValue.length <= 0"
:content="defaultValue.join('、')"
placement="top"
>
<el-select
v-model="value"
:multiple="true"
collapse-tags
:disabled="disabled"
:placeholder="placeholder"
@change="selectChange"
>
<el-option
v-if="needSelectAll && defaultOptions.length > 0"
:label="selectAllLabel"
:value="selectAllValue"
>
{{ defaultOptions.length === defaultValue.length ? '取消' : '' }}{{ selectAllLabel }}
</el-option>
<el-option
v-for="(each, i) in defaultOptions"
:key="i"
:label="each.label"
:value="each.value"
/>
</el-select>
</el-tooltip>
</template>
- js部分
export default {
props: {
defaultValue: {
type: [Array, String, Number],
default() {
return [];
}
},
disabled: {
type: Boolean,
default() {
return false;
}
},
placeholder: {
type: String,
default() {
return '';
}
},
defaultOptions: {
type: Array,
default() {
return [];
}
},
needSelectAll: {
type: Boolean,
default() {
return false;
}
},
selectAllLabel: {
type: String,
default() {
return '全部';
}
}
},
data() {
return {
value: [],
selectAllValue: 'all全部'
};
},
watch: {
defaultValue() {
this.initData();
}
},
created() {
this.initData();
},
methods: {
updateVal(val, needEmit) {
const { defaultOptions } = this;
const list = defaultOptions.map(item => item.value);
this.$emit('update:defaultValue', val.filter(item => list.indexOf(item) >= 0));
if (needEmit) {
this.$nextTick(() => {
this.$emit('change', this.defaultValue);
});
} else { /**/ }
},
selectChange(val) {
const { needSelectAll, selectAllValue, value, defaultValue, defaultOptions } = this;
let arr = value.slice();
if (needSelectAll) {
arr = arr.filter(item => item !== selectAllValue);
if (!this.judgeArrValEqual(arr, defaultValue)) {
this.updateVal(arr);
} else {
if (value.indexOf(selectAllValue) >= 0) {
if (arr.length < defaultOptions.length) {
defaultOptions.forEach(item => {
if (value.indexOf(item.value) < 0) {
value.push(item.value);
} else { /**/ }
});
this.updateVal(value.filter(item => item !== selectAllValue));
} else { /**/ }
} else {
value.splice(0, value.length);
this.updateVal([]);
}
}
} else {
if (!this.judgeArrValEqual(arr, defaultValue)) {
this.updateVal(arr);
} else { /**/ }
}
},
judgeArrValEqual(list1, list2) {
list1 = list1 && list1.length > 0 ? list1 : [];
list2 = list2 && list2.length > 0 ? list2 : [];
const arr1 = list1.slice().sort();
const arr2 = list2.slice().sort();
if (arr1.join(',') === arr2.join(',')) {
return true;
} else {
return false;
}
},
initData() {
const { defaultValue, defaultOptions, value, needSelectAll, selectAllValue } = this;
if (typeof defaultValue === 'string') {
this.updateVal(defaultValue.split(','), false);
return;
} else if (typeof defaultValue === 'number') {
this.updateVal([defaultValue]);
return;
} else { /**/ }
value.splice(0, value.length);
if (needSelectAll) {
if (defaultValue.length === defaultOptions.length && defaultOptions.length > 0) {
value.push(selectAllValue);
} else {
const selectAllIndex = value.indexOf(selectAllValue);
if (selectAllIndex >= 0) {
value.splice(selectAllIndex, 1);
} else { /**/ }
}
} else { /**/ }
value.push(...defaultValue);
}
}
};
3.解析
- Tooltip 文字提示 用来悬浮多选折叠提示,并设置无值时不需要提示处理。
- 在组件初始化和监听传参
defaultValue
变化时调用initData
初始化数据。 - 当选择组件数据切换时调用
selectChange
完善数据全选和取消全选。 - 通过调用
updateVal
方法出发异步数据defaultValue
更新,并按需传递change事件。
4. 具体使用
<template>
<SelectMultibleAll
:default-value.sync="value"
:default-options="options"
:placeholder="请选择"
:need-select-all="needSelectAll"
:disabled="disabled"
@change="selectChange"
/>
</template>
<script>
import SelectMultibleAll from '@/components/SelectMultibleAll.vue';
export default {
components: { SelectMultibleAll },
data() {
return {
value: [],
options: [
{ label: '选项1', value: '值1' },
{ label: '选项2', value: '值2' }
],
needSelectAll: true,
disabled: false
}
},
methods: {
selectChange(val) {
console.log(val);
}
}
}
</script>
效果
代码下载