| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- <template>
- <div class="app-select" @click="onClick">
- <slot :label="inputValue">
- <input class="'app-select__input'" v-model="inputValue" :placeholder="placeholder" readonly />
- </slot>
- <Popup v-model:show="show" position="bottom" teleport="body" round>
- <Picker :columns="columns" @cancel="onCancel" @confirm="onConfirm" />
- </Popup>
- </div>
- </template>
- <script lang="ts" setup>
- import { shallowRef, computed, PropType, watch } from 'vue'
- import { Popup, Picker, PickerConfirmEventParams, FieldInstance } from 'vant'
- const props = defineProps({
- modelValue: {
- type: [Number, String]
- },
- options: {
- type: Array,
- default: () => ([])
- },
- optionProps: {
- type: Object as PropType<{ label?: string; value?: string; }>,
- default: () => ({
- label: 'label',
- value: 'value'
- })
- },
- readonly: {
- type: Boolean,
- default: false
- },
- placeholder: {
- type: String,
- default: '请选择'
- },
- })
- const emit = defineEmits(['update:show', 'update:modelValue', 'confirm'])
- const fieldRef = shallowRef<FieldInstance>()
- const show = shallowRef(false) // 是否弹出选择器
- const selectedIndex = shallowRef(-1)
- const columns = computed(() => {
- if (props.options) {
- return props.options.map((e) => ({
- text: e[props.optionProps.label],
- value: e[props.optionProps.value],
- }))
- }
- return []
- })
- // 当前输入框的值
- const inputValue = computed(() => {
- const item = props.options[selectedIndex.value]
- if (item) {
- return item[props.optionProps.label] ?? ''
- }
- return ''
- })
- const onClick = () => {
- if (!props.readonly) {
- show.value = true
- }
- }
- const onCancel = () => {
- show.value = false
- }
- const onConfirm = ({ selectedIndexes: [index], selectedValues: [value] }: PickerConfirmEventParams) => {
- show.value = false
- if (selectedIndex.value !== index) {
- // 更新当前选中的值
- selectedIndex.value = index
- fieldRef.value?.validate()
- emit('update:modelValue', value)
- emit('confirm', value, index)
- }
- }
- watch(() => [props.modelValue, props.options], ([value, items]) => {
- selectedIndex.value = items.findIndex((e) => e[props.optionProps.value]?.toString() === value?.toString())
- }, {
- immediate: true
- })
- </script>
- <style lang="less" scoped>
- @import './index.less';
- </style>
|