el-selec输入数据后保留数据,并且可以删除

32 阅读2分钟

需求:

使用El-select下拉框,如果没有选择下拉框数据,输入的数据需要保留,且保存的数据可以删除,如果没有删除点击唤起模糊搜索;提交订单时,如果只是输入数据没有选择下拉框,需要划到该下拉框对应的区域,并且根据输入的数据模糊查询

困难点

在看到该需求的时候,首先想到的是在失焦的时候保存数据,聚焦的是时候将输入的值赋值给inputValue,但是发现可以赋值,但是不能删除,只能通过select的clearable清空数据,于是经过查到,看到了select中有一个states对象,于是尝试给states中的inputValue可以解决这个问题,于是就有了下面的代码

<el-select
  ref="voyagePlanIdRef"
  v-model="formData.voyagePlanId" 
  v-select-infinite-scroll="queryShipVoyageOptions"
  class="g-input-box bold select-upper-case voyage-wrapper" 
  popper-class="custom-select-popper"
  :placeholder="请选择"
  :remote-method="queryShipVoyageOptions" 
  filterable 
  clearable 
  remote 
  :fit-input-width="false"
  remote-show-suffix 
  :teleported="false"
  @change="onVoyageChange()"
  @blur="onVoyageBlur"
  @focus="onVoyageFocus"
  @visible-change="onVoyageVisibleChange"
  @clear="onVoyageClear"
>
  <el-option v-for="item in shipVoyageOptions" 
    :key="item.value" 
    :label="item.label" 
    :value="item.value">
   </el-option>
</el-select>
// useSelectOptions 发送请求的hooks
const { shipVoyageOptions, getShipVoyageOptions } = useSelectOptions()

const voyagePlanIdRef = ref<any>(null)
const voyageInputValue = ref<string>('')
const voyageError = ref<boolean>(false)
const voyageChange = ref<boolean>(false)

// 使用防抖解决visible-change和remote-method会发送请求两次请求
const queryShipVoyageOptions = useDebounceFn(async (keyword?: string,isReset?: boolean) => {
  const { carrierId, polId, podId } = formData
  if (!carrierId || !polId || !podId)
    return
  await getShipVoyageOptions({
    onlyAvailable: true, // 只查询最近可用的船期
    carrierId,
    polId,
    podId,
    etd: formData.etd || undefined,
    keyword,
    isReset
  })
}, 200, { maxWait: 600 })

// 选择的下拉数据时将voyageChange修改为true
function onVoyageChange(isInit?: boolean) {
  voyageChange.value = true
}

// 失焦处理
function onVoyageBlur(event:any) {
  // 输入关键字 && 没有选择下拉数据 保存关键字
  const { states: { selectedLabel, selected } } = voyagePlanIdRef.value || {}
  if (event.target.value && !voyageChange.value) {
    voyageInputValue.value = event.target.value
    formData.voyagePlanId = event.target.value
  }
  else if (!event.target.value && !voyageChangeFlag.value && selectedLabel && (selected?.value === selected?.currentLabel)) {
    // 没有输入关键字 && 没有选择 && 原来有值&&值不相等,清空数据
    voyageInputValue.value = ''
    formData.voyagePlanId = ''
    voyageError.value = false
  }
  voyageChange.value = false
}

// 聚焦处理
async function onVoyageFocus() {
  if (voyageInputValue.value && !voyageChange.value) {
    voyagePlanIdRef.value.states.inputValue = voyageInputValue.value
    await queryShipVoyageOptions(voyageInputValue.value, true)
  }
}

// 显示下拉框是将值赋值给states中的inputValue
async function onVoyageVisibleChange(val:boolean) {
  if (val) {
    await onVoyageFocus()
  }
  else if (!val && voyageInputValue.value && !voyageChangeFlag.value) {
    voyagePlanIdRef.value.states.inputValue = voyageInputValue.value
  }
}

// 点击清空图标重置变量
function onVoyageClear() {
  formData.voyagePlanId = ''
  voyageInputValue.value = ''
  voyageChangeFlag.value = false
  voyageError.value = false
  nextTick(() => {
    voyagePlanIdRef.value.states.inputValue = ''
  })
}

// 提交订单
function onSubmitOrder() {
  const {states : { selectedLabel, selected } } = voyagePlanIdRef.value
  if(selectedLabel && (selected.currentLabel === selected.value) && !voyageChange.value ) {
    voyageError.value = true
    const voyageWrapperEl: any = document.querySelector('.voyage-wrapper')
    voyageWrapperEl && voyageWrapperEl.scrollIntoView({ behavior: 'smooth'})
    return
  }
  ......
}