更新记录:
- 2024-05-13:
options
数据源支持传入字符串数组,会自动格式化成 { label: value } 数据。
一、需求
- 点击合计,一键全选。
- 当全选时,点击合计,一键反选。
- 当选中01、02、03时,点击06选项会触发全选。
- 当全选时,点击除ALL的任一选项,会取消全选。
二、应用
<template>
<div class="content">
<p>{{ value}}</p>
<g-select
v-model="value"
:options="list"
allProp="ALL"
multiple
val_lab
:filter="{ label: 'classname', value: 'classcode' }"
@change="selectChange"
></g-select>
</div>
</template>
<script>
export default {
data() {
return {
value: "",
list: [
{ classname: "合计", classcode: "ALL" },
{ classname: "企业财产保险", classcode: "01" },
{ classname: "普通家财保险", classcode: "02" },
{ classname: "工程保险", classcode: "03" },
{ classname: "普通意外保险", classcode: "06" },
],
};
},
methods: {
selectChange(list) {
console.log(this.value, list);
},
},
};
</script>
三、源码
g-select.vue
<template>
<div class="select-container">
<el-select
v-model="val"
:size="size"
:loading="loading"
:multiple="multiple"
:disabled="disabled"
:value-key="filter.value"
:filterable="filterable"
:placeholder="placeholder || '请选择'"
:clearable="clearable"
collapse-tags
:style="{ width }"
@clear="handleClear"
@remove-tag="removeTag"
@change="handleChange($event)"
>
<el-option
class="option"
v-for="(item, index) in list"
:key="index"
:label="
(val_lab ? item[filter.value] + ' - ' : '') + item[filter.label]
"
:value="item[filter.value]"
@click.native="optionClick(item)"
>
</el-option>
</el-select>
</div>
</template>
<script>
export default {
model: {
prop: "value",
event: "input",
},
props: {
value: [String, Number, Array],
width: {
type: String,
default: "220px",
},
disabled: {
type: Boolean,
default: false,
},
multiple: {
type: Boolean,
default: false,
},
size: {
type: String,
default: "small",
},
clearable: {
type: Boolean,
default: true,
},
// 是否可搜索
filterable: {
type: Boolean,
default: true,
},
loading: {
type: Boolean,
default: false,
},
options: {
type: Array,
default: () => [],
},
placeholder: {
type: String,
default: "",
},
// 全选选项值
allProp: {
type: String,
default: "ALL",
},
// 显示内容是否包含值
val_lab: {
type: Boolean,
default: false,
},
filter: {
type: Object,
default: () => {
return {
label: "label",
value: "value",
};
},
},
// 数据格式化
init: {
type: Function,
default: (list) => {
if (Array.isArray(list) && !list.find((v) => typeof v != "string")) {
return list.map((v) => {
return { label: v, value: v };
});
}
return false;
},
},
},
data() {
return {
val: "",
list: [],
};
},
watch: {
value: {
handler(val) {
this.val = val || (this.multiple ? [] : "");
},
immediate: true,
},
options: {
handler(val) {
this.list = val;
if (!val.length) this.val = this.multiple ? [] : "";
let initList = this.init(this.list);
if (initList) this.list = initList;
},
deep: true,
},
},
mounted() {
this.list = this.options || [];
let initList = this.init(this.list);
if (initList) this.list = initList;
},
methods: {
handleChange(value) {
this.val = value;
this.$emit("input", this.val);
},
optionClick(info) {
let lis = [];
if (this.multiple) {
if (this.list.find((v) => v[this.filter.value] == this.allProp)) {
if (info[this.filter.value] == this.allProp) {
// 取消全选
if (this.val.length == this.list.length - 1 && !this.val.includes(this.allProp)) {
this.val = [];
} else {
// 点击全选
this.val = this.list.map((v) => v[this.filter.value]);
lis = this.list;
}
} else {
if (this.val.length == this.list.length - 1) {
// 要把全选选项去掉
if (this.val.includes(this.allProp)) this.val.shift();
// 要把全选选项勾上
else this.val.unshift(this.allProp); // 反向全选
}
}
}
lis = this.list.filter((v) => this.val.includes(v[this.filter.value]));
} else lis = info;
this.$emit("input", this.val);
this.$emit("change", lis);
},
removeTag(val) {
// val 为关闭的标签
if (val == this.allProp) this.val = [];
let lis = this.list.filter((v) =>
this.val.includes(v[this.filter.value])
);
this.$emit("input", this.val);
this.$emit("change", lis);
},
handleClear() {
this.$emit("clear");
this.$emit("input", this.val);
this.$emit("change", this.multiple ? [] : null);
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-select .el-tag {
max-width: 70%;
}
// .option {
// height: 40px;
// font-size: 14px;
// line-height: 40px;
// }
</style>
四、使用说明
props
value
:v-model绑定值。options
:数据源。multiple
:是否多选。allProp
:全选选项值。(默认 ALL)- filter:自定义显示的 key名称 和使用的 value值。(默认 label value)
- disabled:是否禁用。
- val_lab:是否 value key组合显示。(默认只显示 key)
- loading:是否正在从远程获取数据。
- placeholder:占位符。
- width:组件宽度,需要带单位。(默认 200px)
- size:输入框尺寸。(默认 small)
- clearable:是否可以清空选项。(默认 true)
- filterable:是否可搜索。(默认 true)
- init:数据格式化函数。
Event
- change:选中值发生变化时触发。(list) => {}
- list:选中的数据。单选为 Object,多选时为 Array。
目前实现了基本的全选需求,大家如果有更加细致的需求可以参考文档自行增删改。