个人笔记,欢迎指正,不喜勿喷
组件代码
<template>
<div>
<van-field
readonly
clickable
type="textarea"
rows="1"
autosize
:value="displayValue"
:label="label"
:placeholder="placeholder"
@click="showPicker = true"
:rules="rules"
/>
<van-popup v-model="showPicker" position="bottom" v-if="!readonly">
<van-search v-model="searchQuery" placeholder="搜索" />
<van-picker
:default-index="defaultIndex"
show-toolbar
:columns="formattedColumns"
@confirm="onConfirm"
@cancel="showPicker = false"
/>
</van-popup>
</div>
</template>
<script>
export default {
name: "SearchablePicker",
props: {
readonly: {
type: Boolean,
default: false
},
defaultIndex: {
type: Number,
default: 0
},
value: {
type: [Number, String, Array],
default: () => [],
},
columns: {
type: Array,
required: true,
},
label: {
type: String,
default: "选择项",
},
placeholder: {
type: String,
default: "点击选择",
},
multiSelect: {
type: Boolean,
default: false,
},
valueKey: {
type: String,
default: "value", // 默认使用 'value' 作为选项的值
},
labelKey: {
type: String,
default: "name", // 默认使用 'name' 作为选项的标签
},
rules: {
type: Array,
default: () => []
}
},
data() {
return {
searchQuery: "",
showPicker: false,
selectedValues: Array.isArray(this.value)
? [...this.value]
: [this.value],
};
},
computed: {
displayValue() {
const selectedTexts = this.columns
.filter((item) =>
this.multiSelect
? this.selectedValues.includes(item[this.valueKey])
: item[this.valueKey] === this.value
)
.map((item) => item[this.labelKey]);
return selectedTexts.join(", ");
},
formattedColumns() {
let arr = [];
if (this.searchQuery) {
arr = this.columns.filter((option) => {
return option[this.labelKey].includes(this.searchQuery);
});
} else {
arr = this.columns;
}
return arr.map((item) => ({
text: item[this.labelKey],
value: item[this.valueKey],
}));
},
},
watch: {
value: {
immediate: true,
handler(newValue, oldValue) {
// console.log(newValue, oldValue, "dddddd")
if(newValue?.length === oldValue?.length) return
// console.log(newValue, "dddddd", newValue === oldValue)
this.selectedValues = Array.isArray(newValue) ? [...newValue] : [newValue];
}
},
selectedValues(val) {
if (this.multiSelect) {
this.$emit("input", val);
}
},
},
methods: {
onConfirm(selected) {
if (this.multiSelect) {
const valueIndex = this.selectedValues.indexOf(selected.value);
if (valueIndex === -1) {
this.selectedValues.push(selected.value);
} else {
this.selectedValues.splice(valueIndex, 1);
}
this.$emit("input", [...this.selectedValues]);
} else {
this.$emit("input", selected.value);
this.showPicker = false;
}
},
confirmSelection() {
this.$emit("input", [...this.selectedValues]);
this.showPicker = false;
},
},
};
</script>
<style scoped>
</style>
使用方法
<searchable-picker
:default-index="4"
v-model="form.year"
:columns="yearColumns"
valueKey="time"
labelKey="time"
label="年度"
placeholder="点击选择时间"
:rules="[{ required: true, message: '请选择年度' }]"
:readonly="form.targetId !== '-1'"
/>
1223

被折叠的 条评论
为什么被折叠?



