vant下拉选择框(单选、多选)

多选
<template>
	<Picker
         label="label"
         text-column="name"
         :label-width="250"
         :dict-data-list="columns"
         value-column="value"
         v-model="modelValue"
         placeholder="请选择"
         :multiple="true"
         required
         :rules="[{ required: true, message: '请选择' }]"
         :readonly="readonly"
         />
</template>

<script>
import Picker from '@/views/alpaca/components/Picker'

modelValue:"1,2"
columns:[
	{
		text:"选项1",
		value:"1"
	},
	{
		text:"选项2",
		value:"2"
	}
]
</script>
单选
<template>
    <Picker 
        label="label"
        text-column="text"
        v-model="modelValue"
        :dict-data-list="columns"
        value-column="value"
        placeholder="请选择"
        :label-width="180"
        :readonly="readonly"
        required
        :rules="[{ required: true, message: '请选择' }]"
    	/>
</template>

<script>
import Picker from '@/views/alpaca/components/Picker'

modelValue:"1"
columns:[
	{
		text:"选项1",
		value:"1"
	},
	{
		text:"选项2",
		value:"2"
	}
]
</script>
picker组件
<template>
  <div class="clearfix">
    <van-field
      v-model="text"
      :required="required"
      readonly
      is-link
      :class="readonly ? 'dict-select-readonly' : ''"
      autocomplete="off"
      @click="showComponentTypePicker"
      :type="multiple ? 'textarea' : 'text'"
      :autosize="multiple"
      rows="1"
      :label-width="labelWidth"
      :label="label"
      :colon="colon"
      :rules="rules"
      :placeholder="placeholder"
      :disabled="readonly"
    />
    <van-popup
      v-model:show="showPicker"
      round
      position="bottom"
      style="height: 300px"
      :close-on-click-overlay="false"
      :lazy-render="false"
    >
      <template v-if="multiple">
        <!--多选弹出层-->
        <div style="display: flex;justify-content: space-between;padding:0 10px;">
          <div
            @click="onDictSelectCancel"
            style="
              margin-bottom: 15px;
              margin-top: 10px;
              color: #969799;
              cursor: pointer;
              text-align: center;
            "
            >取消</div
          >
          <div
            @click="onDictMultipleSelectConfirm"
            style="
              margin-bottom: 15px;
              margin-top: 10px;
              color: #576b95;
              cursor: pointer;
              text-align: center;
            "
            >确定</div
          >
        </div>
        <van-checkbox-group v-model="checkedList">
          <van-cell-group>
            <van-cell
              v-for="(element, index) in dataList"
              :key="element.value"
              clickable
              :title="element.text"
              @click="toggle(index)"
            >
              <template #right-icon>
                <van-checkbox :name="JSON.stringify(element)" @click.stop/>
              </template>
            </van-cell>
          </van-cell-group>
        </van-checkbox-group>
      </template>
 
      <template v-else>
        <!--单选弹出层-->
        <van-picker
          ref="dictSelectPicker"
          show-toolbar
          v-model="realValuePickerList"
          :columns="dataList"
          @confirm="onDictSelectConfirm"
          @cancel="onDictSelectCancel"
        />
      </template>
    </van-popup>
  </div>
</template>
 
<script>
import { ref, watch } from 'vue'

export default {
  name: 'DictSelect',
  props: {
    dictType: {
      type: String,
      default: '',
    },
    dictDataList: {
      type: Array,
      default: () => [],
    },
    label: {
      type: String,
      default: '字典选择器',
    },
    labelWidth: {
      type: Number,
      default: 100,
    },
    colon: {
      type: Boolean,
      default: false,
    },
    placeholder: {
      type: String,
      default: '请选择',
    },
    textColumn: {
      type: String,
      default: 'dictLabel',
    },
    valueColumn: {
      type: [String, Number],
      default: 'dictValue',
    },
    rules: {
      type: Array,
      default: () => [],
    },
    readonly: {
      type: Boolean,
      default: false,
    },
    required: {
      type: Boolean,
      default: false,
    },
    multiple: {
      type: Boolean,
      default: false,
    },
    modelValue: {
      required: false,
    },
  },
  setup(props, { emit }) {
    const showPicker = ref(false)
    const text = ref('')
    const realValue = ref('')
    const realValuePickerList = ref([])
    const dataList = ref([])
    const checkedList = ref([])

    const createDictData = (data) => {
      dataList.value = data.map(item => ({
        text: item[props.textColumn].toString(),
        value: item[props.valueColumn].toString(), // Ensure conversion to string
      }))
      reloadData()
    }

    const reloadData = () => {
      if (realValue.value) {
        const realValueList = realValue.value.split(',')
        checkedList.value = []
        text.value = ''
        realValueList.forEach(value => {
          const currentItem = dataList.value.find(item => item.value === value)
          if (currentItem) {
            if (props.multiple) {
              checkedList.value.push(JSON.stringify({
                text: currentItem.text,
                value: value,
              }))
            } else {
              realValuePickerList.value.push(value)
            }
            if (text.value === '') {
              text.value = currentItem.text
            } else {
              text.value += ',' + currentItem.text
            }
          }
        })
      }
    }

    const showComponentTypePicker = () => {
      reloadData()
      showPicker.value = true
    }

    const onDictSelectCancel = () => {
      showPicker.value = false
    }

    const onDictSelectConfirm = ({ selectedOptions }) => {
      if (selectedOptions[0]) {
        text.value = selectedOptions[0].text.toString()
        realValue.value = selectedOptions[0].value.toString()
        realValuePickerList.value = [realValue.value]
        emit('update:modelValue', realValue.value)
        emit('changeData', selectedOptions[0])
        showPicker.value = false
      }
    }

    const onDictMultipleSelectConfirm = () => {
      const temTextArray = []
      const temValueArray = []
      checkedList.value.forEach(item => {
        const parsedItem = JSON.parse(item)
        temTextArray.push(parsedItem.text)
        temValueArray.push(parsedItem.value)
      })
      text.value = temTextArray.join(',')
      realValue.value = temValueArray.join(',')
      emit('update:modelValue', realValue.value)
      emit('changeData', { text: text.value, value: realValue.value })
      showPicker.value = false
    }

    const toggle = (index) => {
      checkedList.value[index] = !checkedList.value[index];
    }

    watch(() => props.modelValue, (newValue) => {
      if (typeof newValue === 'string' || typeof newValue === 'number') {
        realValue.value = newValue.toString();
        reloadData()
      } else {
        realValue.value = '';
      }
    }, { immediate: true })

    watch(() => props.dictDataList, (newData) => {
      if (newData && newData.length > 0) {
        createDictData(newData)
      }
    }, { immediate: true })

    return {
      showPicker,
      text,
      realValue,
      realValuePickerList,
      dataList,
      checkedList,
      showComponentTypePicker,
      onDictSelectCancel,
      onDictSelectConfirm,
      onDictMultipleSelectConfirm,
      toggle,
    }
  },
}
</script>
 
<style scoped>
.van-cell {
  padding: 10px 20px;
}
.dict-select-readonly {
  pointer-events: none;
}
.van-cell--required::before {
  position: absolute;
  left: -3px;
  color: #ee0a24;
  font-size: 14px;
  content: '*';
}
</style>

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值