uni-combox 使用数组对象

该文章已生成可运行项目,
<uni-combox
          v-if="dataSource && dataSource.length > 0"
          labelKey="shelves_code"
          valueKey="shelves_id"
          :candidates="dataSource"
          v-model="selectValue"
          emptyTips="这里啥都没有"
          placeholder="请选择所在城市"
          @input="comboxInputHandle"
        ></uni-combox> 



const dataSource = ref([{ shelves_id: 0, shelves_code: 'aa' }])
<template>
  <view class="uni-combox" :class="border ? '' : 'uni-combox__no-border'">
    <view v-if="label" class="uni-combox__label" :style="labelStyle">
      <text>{{ label }}</text>
    </view>
    <view class="uni-combox__input-box">
      <input
        class="uni-combox__input"
        type="text"
        :focus="firstFocus"
        :placeholder="placeholder"
        placeholder-class="uni-combox__input-plac"
        v-model.trim="inputVal"
        @input="onInput"
        @focus="onFocus"
        @blur="onBlur"
        @confirm="onEnter"
      />
      <uni-icons
        :type="showSelector ? 'top' : 'bottom'"
        size="14"
        color="#999"
        @tap="toggleSelector"
      />
    </view>
    <view class="uni-combox__selector" v-if="showSelector">
      <view class="uni-popper__arrow"></view>
      <scroll-view scroll-y="true" class="uni-combox__selector-scroll">
        <view class="uni-combox__selector-empty" v-if="filterCandidatesLength === 0">
          <text>{{ emptyTips }}</text>
        </view>
        <view
          class="uni-combox__selector-item"
          v-for="(item, index) in filterCandidates"
          :key="index"
          @tap="onSelectorClick(index)"
        >
          <text>{{ item[`${labelKey}`] }}</text>
        </view>
      </scroll-view>
    </view>
  </view>
</template>

<script>
export default {
  name: 'uniCombox',
  emits: ['input', 'update:modelValue', 'scan-success'],
  props: {
    border: {
      type: Boolean,
      default: true,
    },
    label: {
      type: String,
      default: '',
    },
    labelWidth: {
      type: String,
      default: 'auto',
    },
    placeholder: {
      type: String,
      default: '',
    },
    candidates: {
      type: Array,
      default() {
        return []
      },
    },
    emptyTips: {
      type: String,
      default: '无匹配项',
    },
    labelKey: {
      type: String,
      default: 'dictName',
    },
    valueKey: {
      type: String,
      default: 'dictId',
    },
    modelValue: {
      type: [String, Number],
      default: '',
    },
  },
  data() {
    return {
      showSelector: false,
      firstFocus: false,
      inputVal: '',
      dictVal: '',
      filterCandidates: [],
    }
  },
  computed: {
    labelStyle() {
      return this.labelWidth === 'auto' ? '' : `width: ${this.labelWidth}`
    },
    filterCandidatesLength() {
      return this.filterCandidates.length
    },
  },
  watch: {
    modelValue: {
      handler(newVal) {
        if (this.candidates.length > 0) {
          const selectedItem = this.candidates.find((item) => item[this.valueKey] === newVal)
          if (selectedItem) {
            this.inputVal = selectedItem[this.labelKey]
          }
        }
      },
      immediate: true,
    },
    candidates: {
      handler(newCandidates) {
        if (newCandidates.length > 0 && this.dictVal) {
          const obj = newCandidates.find((item) => item[this.valueKey] === this.dictVal)
          if (obj) {
            this.inputVal = obj[this.labelKey]
          }
        }
        this.filterCandidates = newCandidates.filter((item) =>
          item[this.labelKey].toString().includes(this.inputVal),
        )
      },
      immediate: true,
    },
  },
  methods: {
    focusEvent() {
      this.firstFocus = false
      this.$nextTick(() => {
        this.firstFocus = true
      })
    },
    toggleSelector() {
      this.showSelector = !this.showSelector
    },
    onFocus() {
      this.filterCandidates = this.candidates.filter((item) =>
        item[this.labelKey].toString().includes(this.inputVal),
      )
      this.showSelector = true
    },
    onBlur() {
      setTimeout(() => {
        this.showSelector = false
      }, 150)
    },
    onSelectorClick(index) {
      const selectedItem = this.filterCandidates[index]
      this.dictVal = selectedItem[this.valueKey]
      this.inputVal = selectedItem[this.labelKey]
      this.showSelector = false
      this.$emit('input', this.dictVal)
      this.$emit('update:modelValue', this.dictVal)
    },
    onInput() {
      this.filterCandidates = this.candidates.filter((item) =>
        item[this.labelKey].toString().includes(this.inputVal),
      )
      this.$emit('input', this.dictVal)
      this.$emit('update:modelValue', this.dictVal)
    },
    // 处理扫码事件
    changeScanshelvesHandel() {
      uni.scanCode({
        scanType: ['barCode', 'qrCode', 'datamatrix', 'pdf417'],
        success: (res) => {
          this.inputVal = res.result // 设置扫码返回的值
          this.filterCandidates = this.candidates.filter((item) =>
            item[this.labelKey].toString().includes(this.inputVal),
          )
          // this.dictVal = res.result // 设置筛选后的值

          const selectedItem = this.filterCandidates.find((item) =>
            item[this.labelKey].toString().includes(this.inputVal.trim()),
          )

          if (selectedItem) {
            // 如果找到匹配项,更新 dictVal 和 inputVal
            this.dictVal = selectedItem[this.valueKey]
            this.inputVal = selectedItem[this.labelKey]

            // Emit the scan result to the parent component
            this.$emit('scan-success', res.result) // 将扫码结果传递给父组件
            this.$emit('input', this.dictVal)
            this.$emit('update:modelValue', this.dictVal)
          }
        },
      })
    },
    // 回车事件处理函数
    onEnter() {
      const selectedItem = this.filterCandidates.find((item) =>
        item[this.labelKey].toString().includes(this.inputVal.trim()),
      )
      if (selectedItem) {
        // 如果找到匹配项,更新 dictVal 和 inputVal
        this.dictVal = selectedItem[this.valueKey]
        this.inputVal = selectedItem[this.labelKey]

        // 更新父组件中的值
        this.$emit('input', this.dictVal) // 触发输入事件
        this.$emit('update:modelValue', this.dictVal) // 更新 modelValue
      }
    },
  },
}
</script>

<style lang="scss">
.uni-combox {
  font-size: 14px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  padding: 6px 10px;
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: center;
}

.uni-combox__label {
  font-size: 16px;
  line-height: 22px;
  padding-right: 10px;
  color: #999999;
}

.uni-combox__input-box {
  position: relative;
  display: flex;
  flex: 1;
  flex-direction: row;
  align-items: center;
}

.uni-combox__input {
  flex: 1;
  font-size: 14px;
  height: 22px;
  line-height: 22px;
}

.uni-combox__input-plac {
  font-size: 14px;
  color: #999;
}

.uni-combox__selector {
  position: absolute;
  top: calc(100% + 12px);
  left: 0;
  width: 100%;
  background-color: #ffffff;
  border: 1px solid #ebeef5;
  border-radius: 6px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  z-index: 2;
  padding: 4px 0;
}

.uni-combox__selector-scroll {
  max-height: 200px;
  box-sizing: border-box;
}

.uni-combox__selector-empty,
.uni-combox__selector-item {
  display: flex;
  cursor: pointer;
  line-height: 36px;
  font-size: 14px;
  text-align: center;
  padding: 0px 10px;
}

.uni-combox__selector-item:hover {
  background-color: #f9f9f9;
}

.uni-popper__arrow,
.uni-popper__arrow::after {
  position: absolute;
  display: block;
  width: 0;
  height: 0;
  border-color: transparent;
  border-style: solid;
  border-width: 6px;
}

.uni-popper__arrow {
  top: -6px;
  left: 10%;
  margin-right: 3px;
  border-top-width: 0;
  border-bottom-color: #ebeef5;
}

.uni-popper__arrow::after {
  content: ' ';
  top: 1px;
  margin-left: -6px;
  border-top-width: 0;
  border-bottom-color: #fff;
}

.uni-combox__no-border {
  border: none;
}
</style>

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值