初次使用vant ui,想使用类似 element ui中的 select 组件,结果文档中并没有该组件,无奈自己封装

1. 自定义组件代码(van-select)

<template>
  <div>
    <van-field
        v-model="text"
        v-bind="$attrs"
        readonly
        is-link
        :name="name"
        @click="show = !show"
    >
    </van-field>
    <van-popup :show="show" round position="bottom">
      <van-picker
          :columns="columns"
          show-toolbar
          :value-key="valueKey"
          :title="$attrs.label"
          @cancel="show = !show"
          @confirm="onConfirm"
      ></van-picker>
    </van-popup>
  </div>
</template>

<script>
import {nextTick, onMounted, reactive, toRefs, watch} from "vue";

export default {
  name: 'vanSelect',
  model: {
    prop: 'modelValue'
  },
  props: {
    // 下拉框数据
    columns: {
      type: Array
    },
    // 父组件绑定的 v-model
    modelValue: {
      type: String
    },
    // 指定 下拉框数据 显示属性名
    valueKey: {
      type: String,
      default: "nr"
    }
  },
  setup(props, ctx) {
    onMounted(()=>{
      nextTick(()=>{
        reShow();
      })
    })
    const data = reactive({
      show: false,
      bm: "",
      text:""
    })
    const onConfirm = (value) => {
      data.text = value.nr;
      data.bm = value.bm;
      data.show = !data.show;
    }
    // 回显
    const reShow = () => {
      if(props.modelValue) {
        props.columns.forEach(res => {
          if (res.bm == props.modelValue) {
            data.text = res.nr;
          }
        })
      }
    }
    watch(()=>data.bm ,(newVal, oldVal) => {
      ctx.emit('update:modelValue', newVal);
    })
    watch(()=>props.columns,(newVal,oldVal)=>{
      //处理异步数据回显
      reShow();
    })
    watch(()=>props.modelValue,(newVal,oldVal)=>{
      //处理异步数据回显
      reShow();
    })
    return {
      ...toRefs(data),
      onConfirm
    }
  }
};
</script>
<style></style>


2.组件使用

<template>
  <van-form class="figure" label-width="5em" @submit="" ref="vanForm" validate-trigger="onChange">
    <van-cell-group inset>
      <van-select
          clearable
          label="身份"
          name="role"
          placeholder="请选择身份"
          v-model="form.role"
          v-bind:columns="itemList"
          :rules="[{ required: true, message: '请选择身份' }]"
      />
    </van-cell-group>
  </van-form>
</template>

<script>
import {ref, toRefs, reactive, onMounted} from 'vue'
import VanSelect from "@/components/van-select.vue";
export default {
  name: 'Demo',
  components: {VanSelect},
  props: {},
  setup(props, ctx) {
    const data = reactive({
      itemList: [
        {
          bm: '5',
          nr: '律师'
        },
        {
          bm: '1',
          nr: '公安机关'
        },
        {
          bm: '2',
          nr: '检察院'
        },
        {
          bm: '3',
          nr: '法院'
        },
        {
          bm: '4',
          nr: '安全机关'
        },
        {
          bm: '9',
          nr: '其他'
        }
      ],
      form: {
        role: "",
      },
    })
    return {
      ...toRefs(data)
    }
  }
}
</script>
<style scoped>

</style>

3. 效果如下

在这里插入图片描述
在这里插入图片描述
总体思路就是 van-select 中的filed 显示选中选项的文字,将选项中的编码赋值给父组件,后期可以将 传入的数组 属性名改为动态的,进一步优化和解耦

Logo

前往低代码交流专区

更多推荐