展示效果
组件引用
<selected-picker
v-model="form.famAddr3"
label="省份"
:columns="provinces"
:columnsLength="provinces.length"
placeholder="请选择"
input-align="right"
error-message-align="right"
@onConfirm="onConfirmFam3"
:error-message="errorInfo.famAddr3"
:rule="rules.famAddr3"
:readonly='!isDisable'
></selected-picker>
export default class index extends Vue{
public errorInfo: object = {
famAddr3: ''
}
public form: object = {
famAddr3: '',
}
public rules: any = {
famAddr3: [
{
required: true,
message: "请选择省份"
}
],
}
// 校验只显示一次问题解决
onConfirmFam3(){
this.errorInfo.famAddr3 = ''
}
}
组件封装
selectedPicker封装
<template>
<div class="selected-picker">
<van-field :label='label' readonly class="for-add-border" input-align='right' :error-message='!errorMessage?"":errorMessage' error-message-align='right'>
<template #input >
<span @click="onHandUpPicker">{{value?(value.length>0?value.join(" "):value.length == 0?placeholder: value):placeholder}}</span>
<span @click="onHandUpPicker" class="extra-con"></span>
</template>
<template #button v-if='value && value.length>0'>
<van-icon name="close" class="close-icon" @click="handleClear"/>
</template>
</van-field>
<popup-picker :selected='value && value.length>0 ? Number(columns[0].values.indexOf(value[0])): 0' :show="showDialog" :columns="columns" :columnsLength="columnsLength" @onCancel="onCancelPopup" @onConfirm="onConfirmPopup" @onPickerChange="onPickerChange"></popup-picker>
</div>
</template>
<script lang="ts">
import {Component, Vue, Prop, Emit, Watch} from "vue-property-decorator"
import {PopupPicker} from "@/components"
import validators from "@/utils/utils"
@Component({
components:{
"popup-picker": PopupPicker
}
})
export default class SelectedPicker extends Vue{
/**
* @param error-message-align 错误信息位置
* @param input-align 输入框文本位置
* @param required-value 触发点击事件之前必须存在且不为false的值
* @event onCalcel 点击取消时的回调
* @event onConfirm 点击确定时的回调
* @event input 触发oninput事件的回调,主要用来绑定v-model
* @event onPickerChange picker的值被修改时被触发
* @event required 校验required-value未通过时触发
* */
@Prop() label?: string //表单名称
@Prop() placeholder?: string //placeholder
@Prop() columns!: Array<any> //下拉选择列表
@Prop() columnsLength!: number //已选择的列数
@Prop() value!: any //value,与v-model对应
@Prop() rule?: any //校验规则
@Prop() disabled?: boolean
@Prop() readonly?:{
type: boolean,
default: false
}
public showDialog: boolean = false
public errorMessage: string = ""
onHandUpPicker(){
if(this.$attrs["required-value"] == ""){
this.onRequired()
return
}
if(this.readonly || this.columns[0].values.length == 0) return
this.showDialog = true
}
// 清除选项
handleClear() {
this.onConfirmPopup('', 0)
}
@Emit("onCancel")
onCancelPopup(){
this.showDialog = false
}
@Emit("onConfirm")
onConfirmPopup(values: any, index: any){
this.showDialog = false
this.onChange(values)
this.errorMessage = ""
return !values[0] ? '' : values
}
@Emit("input")
onChange(values: any){
return values
}
@Emit("onPickerChange")
onPickerChange( {values, index}: any ){
this.errorMessage = ""
return { values, index }
}
@Emit("required")
onRequired(){
}
@Watch("$attrs",{deep: true})
onAttrsChange(newVal: any, old: any){
if(newVal["error-message"] != old["error-message"]){
this.errorMessage = newVal["error-message"]
}
}
}
</script>
<style scoped lang="less">
.selected-picker:not(:last-child){
.for-add-border{
&::after{
content: ' ';
position: absolute;
pointer-events: none;
box-sizing: border-box;
left: 0.4rem;
right: 0;
bottom: 0;
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
border-bottom: 0.026667rem solid #ebedf0;
}
}
}
.selected-picker-title{
// max-width: 112.5px;
}
.selected-picker-show{
// text-align: left;
clear:both;
}
.has-selected-picker{
color: #323233;
}
.extra-con{
float: right;
}
</style>
popupPicker组件封装
将popup与van-picker封装成一个组件方便引用
<template>
<van-popup v-model="show" position="bottom" :close-on-click-overlay="false">
<div>
//default-index:用于判断默认值并选中默认值
<van-picker :default-index="selected" :show-toolbar="true" @confirm="onConfirmPopup" @cancel="onCancelPopup" :columns="columns" @change="onPickerChange" ref='picker'/>
</div>
</van-popup>
</template>
<script lang="ts">
import {Component, Vue, Prop, Emit, Watch} from "vue-property-decorator"
@Component
export default class PopupPicker extends Vue {
@Prop() show!: boolean
@Prop() columns!: Array<any>
@Prop() columnsLength!: number
@Prop() selected!: number
public pickerResult: Array<string> = [this.columns[0].values[0]]
@Emit("onCancel")
onCancelPopup(){}
@Emit("onConfirm")
onConfirmPopup(values: any, index: any){
return !values[0] ? '' : values
}
@Emit("onPickerChange")
onPickerChange(picker: any, values: any, index: any){
this.pickerResult[index] = picker.getColumnValue(index)
// console.log(this.$refs['picker'].setValues,values)
return { values, index }
}
@Watch("columnsLength")
onDataChange(newVal: number, old: number){
if(newVal > old){
this.pickerResult.push(this.columns[newVal - 1].values[0])
}
}
}
</script>
<style scoped lang="less">
.popup-header{
padding:15px;
border: 1px solid #e5e5e5;/*no*/
}
</style>
有问题欢迎提问和指正!