foreword
For the selector component, the picker component in vant is a very suitable choice. It not only provides flexible configuration options, but also can be easily combined with other vant components to help us quickly build beautiful and easy-to-use mobile pages. In this article, I will introduce how to perform secondary packaging based on vant 's picker component to better meet actual business needs.
Implementation ideas
- First define a subcomponent page to encapsulate the selector;
- Introduce and register the encapsulation component (subcomponent) in the parent component (the page used), and then use it in the page. In the parent component, bind multiple attributes to the label (registered component name), and the attribute needs to be passed to mount The value of is received by receiving data
props
in the subcomponent (encapsulation file); - Customize the determined event in the child component. After calling this event, the child component
this.$emit('自定义事件名',要传递的数据)
sends the data that the parent component can listen to, and finally the parent component listens to the child component event, calls the event and receives the passed data.
defined parameters
parameter | describe |
---|---|
selectValue | bind valuemodel |
keyValue | bound key field |
keyLabel | bound value field |
columns | The bound option data source |
required | Whether to display red * check |
rules | Validation rules |
required | Is it required? |
confirm | The selected callback function |
package file
<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>
use file
<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>