Vue3 element-plus 下拉分页 select分页

由于用 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 没有额外的代码,所以就不贴了

posted @ 2022-03-11 15:03  骚猪佩琦  阅读(3509)  评论(0编辑  收藏  举报