因为vant2的下拉列表需要input框和弹框组合使用,所以自己封装了一下,点击确定可以返回选择的对象,并且支持多个下拉列表共用一个确定方法。 组件的特点:
- 点击显示下拉列表的弹框,点击确定给父组件返回选中的内容,包括
text
(选中的文字内容)和value
(选中的值); - 当页面有多个下拉框的时候,可以共用
confirm
方法,从而简化代码; - 支持下拉列表默认回显功能
组件内容
<template>
<div class="pickerPop">
<van-field
readonly
clickable
:required="required"
:name="fieldName"
:value="fieldValueText"
:label="fieldLabel"
:rules="rules"
placeholder="请选择"
@click="showPicker = true"
/>
<van-popup v-model="showPicker" position="bottom">
<van-picker
:title="defaultTitle"
v-model="selectedValue"
:default-index="selectedIndex"
show-toolbar
value-key="text"
:columns="columns"
@confirm="(value) => onConfirm(fieldType, value)"
@cancel="showPicker = false"
/>
</van-popup>
</div>
</template>
<script>
/*
* 1、这是个封装的下拉列表组件,
* 如果需要显示默认值需要在组件上写 v-if="isDictRender" defaultValue="你的默认显示的下拉框的值"
* v-if是必须的,否则赋值和获取列表数据是异步,无法回显
* 2、如果一个页面多次需要这个组件,可以传入fieldType="你的下拉框类型"
* 这样的话需要复用的下拉框的确定事件就可以写一个如 @confirm="onConfirm"
* 共用onConfirm()方法,根据返回值返回的type字段进行区分
*
* */
export default {
name: 'pickerPop',
props: {
// 如果有多个下拉框存在的时候可以用这个判断
fieldType: {
type: String,
default: ''
},
// 前面红色*号
required: {
type: Boolean,
default: false
},
// 验证
rules: {
type: Array,
},
// 提交表单的标识符 // 根据你的需求,可以不传
fieldName: {
type: String,
default: ''
},
// 标题
defaultTitle: {
type: String,
default: ''
},
// label显示的文字
fieldLabel: {
type: String,
default: ''
},
// 传进来的默认值
defaultValue: {
type: [String, Number], // 根据你的需求定义类型
default: null,
},
// 要显示的文字 如果要做回显就给这个值赋值
fieldValueText: {
type: String,
default: ''
},
// 下拉列表数据
columns: {
type: Array,
required: true
}
},
data() {
return {
showPicker: false,
selectedValue: this.defaultValue, // 使用 prop 的默认值来初始化 selectedValue
selectedIndex: '', // 默认回显
};
},
created(){
},
mounted(){
// 根据默认值获取当前数据所在字典表数组的索引
this.selectedIndex = this.columns.findIndex((item) => item.value == this.defaultValue)
},
computed: {},
methods: {
onConfirm(type, value) {
// console.log('Type:', type); // 输出 'Type'
// console.log('Value:', value); // 输出选中的值
/*
* 返回的这个type是根据组件传入的参数,
* 当有多个下拉框存在的时候用这个组件可以用一个confirm方法通过type进行判断,
* 不用再多写很多确定事件了
* */
this.$emit('confirm', {
type: type?type:null,
text: value.text,
value: value.value
});
this.showPicker = false;
}
}
};
</script>
<style scoped lang="less">
.van-cell--borderless:after, .van-cell:last-child:after {
display: initial;
}
</style>
父组件这样使用:
<template>
<div class="box">
<pickerPop
v-if="isDictRender"
defaultValue="O"
fieldName="bloodTypeText"
fieldLabel="血型"
:fieldValueText="bloodTypeText"
:columns="columns_blood"
defaultTitle="血型"
@confirm="onConfirm"
/>
</div>
</template>
<script>
export default {
data() {
return {
isDictRender: false,
bloodValue: '', // 血型
bloodTypeText: '', // 血型-文字
// 血型字典表
columns_blood: [
{ text: 'A型', value: 'A' },
{ text: 'B型', value: 'B' },
{ text: 'AB型', value: 'AB' },
{ text: 'O型', value: 'O' },
]
}
},
methods: {
// 血型确定
onConfirm(value) {
console.log(value)
this.bloodTypeText = value.text;
this.bloodValue = value.value;
},
},
created() {
}
}
</script>
<style scoped>
</style>