需求:
使用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
}
......
}