由於用 input 實現下拉分頁不太理想,轉換了一個角度,用 select 實現,以下是具體實現(script-setup TS)
script-setup
<script lang="ts">
import { defineComponent } from 'vue'
export default defineComponent({ name: 'LabelSelectCpm' })
</script>
<script setup lang="ts">
import { ref, reactive } from 'vue'
// const emit = defineEmits([])
// select 綁定的 v-model
const value = ref()
const searchKeyword = ref()
//dom 事件節點
const dom = ref()
const loading = ref(false)
// select-options 數據源
const options = ref([])
// 分頁控制
const requsetObj = reactive({
page: 1,
size: 50,
})
/**
* 加載接口數據
* @return Promise
*/
const loadData = async () => {
return new Promise((res, rej) => {
setTimeout(() => {
res(
Array.from(
{ length: requsetObj.size * requsetObj.page },
(v, i) => ({ label: `label${i}`, value: `value${i}` })
)
)
}, 300)
})
}
/**
* @param {string} query 輸入的搜索關鍵詞
* @param {function} fn 需要在接口數據返回后執行的回調
*/
const remoteMethod = (query: string, fn?: Function) => {
loading.value = true
if (query) {
/* 記錄輸入的關鍵詞 */
searchKeyword.value = query
loadData().then((res: any) => {
console.log(res)
options.value = res
loading.value = false
fn && fn()
})
} else {
/* 初始化數據邏輯 */
loadData().then((res: any) => {
console.log(res)
options.value = res
loading.value = false
fn && fn()
})
}
}
const selectChange = (val: any) => {
const selectVal = options.value.filter((e: any) => e.value == val)
console.log('當前選中', selectVal)
}
/* 滾動監聽函數 */
const scrollAddEventFn = (e) => {
const self = e.target as any
if (self.scrollHeight - self.scrollTop <= self.clientHeight) {
console.log('分頁查詢')
requsetObj.page++
remoteMethod(searchKeyword.value)
}
}
const visibleChange = (isShow: any) => {
if (isShow) {
// 下拉框顯示時,渲染數據,初始化滾動監聽
remoteMethod(searchKeyword.value, () => {
/* 在數據渲染完之后的回調 */
/* 初始化滾動監聽 (由於 dom 渲染未完成,所以需要開啟一個 timeout 在 1s 后實現監聽) */
const parentDom = document.querySelectorAll(
'.el-select-dropdown__wrap.el-scrollbar__wrap.el-scrollbar__wrap--hidden-default'
) as any
setTimeout(() => {
parentDom.forEach((e: any, idx: number) => {
if (
e.querySelector('.LabelSelectCpmBox') &&
e.querySelector('.LabelSelectCpmBox').children &&
e.querySelector('.LabelSelectCpmBox').children.length >
0
) {
dom.value = parentDom[idx]
dom.value.addEventListener(
'scroll',
scrollAddEventFn,
false
)
}
})
}, 1000)
})
} else {
// 移除滾動監聽
dom.value?.removeEventListener('scroll', scrollAddEventFn, false)
options.value = []
}
}
</script>
template
<template>
<div class="LabelSelectCpm">
<el-select
v-model="value"
:multiple="false"
filterable
remote
reserve-keyword
placeholder="輸入關鍵詞搜索"
:remote-method="remoteMethod"
@change="selectChange"
@visible-change="visibleChange"
:loading="loading"
>
<div class="LabelSelectCpmBox">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
>
</el-option>
</div>
</el-select>
</div>
</template>
css 沒有額外的代碼,所以就不貼了