前言
对于选择器组件,vant 中的 picker 组件是一个非常合适的选择。它不仅提供了灵活的配置选项,还可以很方便地与其他 vant 组件结合使用,帮助我们快速搭建出漂亮、易用的移动端页面。在本文中,我将为大家介绍如何基于 vant 的 picker 组件进行二次封装,以便更好地满足实际的业务需求。
实现思路
- 首先定义一个子组件页面用来封装选择器;
- 在父组件中(使用的页面)引入封装组件(子组件)并注册,然后在页面中使用,在父组件中给标签(注册的组件名)上绑定多个属性, 属性上挂载需要传递的值,通过
props
在子组件(封装文件)接收数据; - 在子组件中自定义确定的事件,调用这个事件后,子组件通过
this.$emit('自定义事件名',要传递的数据)
发送父组件可以监听的数据,最后父组件监听子组件事件,调用事件并接收传递过来的数据。
定义的参数
参数 | 描述 |
---|---|
selectValue | 绑定值 model |
keyValue | 绑定的 key 字段 |
keyLabel | 绑定的 value 字段 |
columns | 绑定的 option 数据源 |
required | 是否显示红色 * 校验 |
rules | 校验规则 |
required | 是否必填 |
confirm | 选中的回调函数 |
封装文件
<template>
<div>
<van-field v-model="textValue" v-bind="$attrs" :name="$attrs.name" :rules="rules" :required="required" :readonly="readonly"
:is-link="islink" @click="show = !show" />
<van-popup v-model="show" get-container="body" position="bottom">
<van-picker :columns="columns" show-toolbar :value-key="keyValue" :title="$attrs.label" @cancel="show = !show" @confirm="onConfirm">
<template #option="option">
{{ option[keyLabel] }}
</template>
</van-picker>
</van-popup>
</div>
</template>
<script>
export default {
props: {
required: {
type: Boolean,
},
readonly: {
type: Boolean,
},
islink: {
type: Boolean,
},
columns: {
type: Array,
},
rules: {
type: Array,
},
selectValue: {
type: String,
},
keyValue: {
type: String,
},
keyLabel: {
type: String,
},
},
data() {
return {
show: false,
textValue: "",
selectOptions: [],
};
},
methods: {
onConfirm(obj) {
this.textValue = obj.label;
this.show = !this.show;
this.$emit("confirm", obj);
},
formatterValue(value) {
let str = "";
if (!this.columns.length || !value.length) {
str = "";
} else {
let oArr = this.columns.filter((item) => {
return item[this.keyValue].toString() == value.toString();
});
str = oArr[0][this.keyLabel];
}
return str;
},
//根据key值格式化成picker需要的option格式
formatColumnsByKey() {
let arr = [];
let value = this.keyValue ? this.keyValue : "value";
let label = this.keyLabel ? this.keyLabel : "label";
this.columns.map((item) => {
arr.push({
label: item[label],
value: item[value],
});
});
this.selectOptions = arr;
},
},
watch: {
columns: {
handler(newValue) {
this.textValue = this.formatterValue(
this.selectValue ? this.selectValue : ""
);
},
deep: true,
immediate: true,
},
selectValue: {
handler(newValue) {
this.textValue = this.formatterValue(newValue ? newValue : "");
},
deep: true,
immediate: true,
},
},
};
</script>
使用文件
<template>
<div>
<van-form validate-first>
<VanSelect name="qylx" label="企业类型" placeholder="请选择企业类型" :selectValue="qylx" :keyValue="`value`" :keyLabel="`label`" :required="true"
:readonly="true" :columns="qylxOption" :rules="rules.qybh" @confirm="qylxConfirm" />
<div class="btnBomBox">
<van-button round size="small" block @click="submitOn" type="info">提交</van-button>
</div>
</van-form>
</div>
</template>
<script>
import VanSelect from "@/components/vanSelect/index";
export default {
components: {
VanSelect,
},
data() {
return {
qylx: "",
qylxOption: [
{ label: "自营企业", value: "1" },
{ label: "其他企业", value: "2" },
],
rules: {
qybh: [
{
required: true,
message: "请选择企业类型",
},
],
},
};
},
methods: {
// 点击确定
qylxConfirm(value) {
this.qylx = value.value;
},
// 提交
submitOn() {
console.log(this.qylx);
},
},
};
</script>
<style scoped>
.btnBomBox {
padding: 0px 16px;
display: flex;
justify-content: center;
}
</style>