645 字
3 分钟
el-select和el-cascader多选数据格式修改为字符串
为什么要修改多选数据格式
在使用element-ui的el-select和el-cascader组件时,多选数据格式是数组,而后端的实际需求是数组中的每个元素是逗号隔开的字符串,而不是对象。在使用中就需要转换数据类型,接收后端数据时时把字符串转为数组,在发送数据时,又把数组转为字符串。十分繁琐而且随意修改数据类型是很不提倡的行为。于是就想着修改组件的数据类型,使数据类型可以自定义。原本是要修改element-ui的源码并提交,但是发现element-ui已经很久不维护了,于是就只扩展element-ui的功能,而不修改原有代码。
el-select
el-select组件的multiple属性是默认为false的,所以默认情况下是单选,如果需要多选,需要设置multiple属性为true。新建以下自定义组件str-select并全局注册,使用时直接使用str-select组件即可,组件的所有属性不变。
<template>
<div>
<el-select
:value="internalValue"
@change="handleChange"
v-bind="filteredAttrs"
v-on="filteredListeners"
ref="select"
:multiple="isMultiple"
>
<template v-for="(slotFn, name) in $scopedSlots" :slot="name" slot-scope="slotData">
<slot :name="name" v-bind="slotData"></slot>
</template>
</el-select>
</div>
</template>
<script>
export default {
name: "StrSelect",
inheritAttrs: false,
props: {
value: {
type: String,
default: "",
},
multiple: {
type: Boolean,
default: false,
},
},
data() {
return {
internalValue: this.multiple ? [] : "",
};
},
computed: {
filteredAttrs() {
const { value, multiple, ...restAttrs } = this.$attrs;
return restAttrs;
},
filteredListeners() {
const { input, change, ...restListeners } = this.$listeners;
return restListeners;
},
isMultiple() {
return this.multiple;
},
},
watch: {
value: {
immediate: true,
handler(newValue) {
if (this.isMultiple) {
this.internalValue = newValue ? newValue.split(",").map((item) => item.trim()) : [];
} else {
this.internalValue = newValue || "";
}
},
},
internalValue: {
handler(newValue) {
if (this.isMultiple) {
this.$emit("input", newValue.join(","));
} else {
this.$emit("input", newValue);
}
},
},
},
methods: {
handleChange(newValue) {
this.internalValue = newValue;
if (this.isMultiple) {
this.$emit("change", newValue.join(","));
} else {
this.$emit("change", newValue);
}
},
blur() {
this.$refs.select.blur();
},
focus() {
return this.$refs.select.focus;
},
},
};
</script>
<style scoped>
</style>
el-cascader
el-cascader组件默认就返回数组。新建以下自定义组件str-cascader并全局注册,使用时直接使用el-cascader组件即可,除了emitPath以外,组件的所有属性不变,目前的str-cascader只支持emitPath为 false。
<template>
<div>
<el-cascader
:value="internalArray"
@change="handleChange"
v-bind="filteredAttrs"
v-on="filteredListeners"
ref="cascader"
>
<template v-for="(slotFn, name) in $scopedSlots" :slot="name" slot-scope="slotData">
<slot :name="name" v-bind="slotData"></slot>
</template>
</el-cascader>
</div>
</template>
<script>
export default {
name: 'StrCascader',
inheritAttrs: false,
props: {
value: {
type: String,
default: ''
}
},
data() {
return {
internalArray: []
};
},
computed: {
filteredAttrs() {
const { value, ...restAttrs } = this.$attrs;
return restAttrs;
},
filteredListeners() {
const { input,change, ...restListeners } = this.$listeners;
return restListeners;
}
},
watch: {
value: {
immediate: true,
handler(newValue) {
if (newValue) {
this.internalArray = newValue.split(',').map(item => item.trim());
} else {
this.internalArray = [];
}
}
},
internalArray: {
handler(newValue) {
console.log(newValue,"newValue22");
this.$emit('input', newValue.join(','));
}
}
},
methods: {
handleChange(newValue) {
this.internalArray = newValue;
console.log(newValue,"newValue11");
this.$emit('change', newValue.join(','));
},
getCheckedNodes(){
return this.$refs.cascader.getCheckedNodes()
},
clearCheckedNodes(){
return this.$refs.cascader.$refs.panel.clearCheckedNodes()
},
}
};
</script>
<style scoped>
</style>

