<template>

    <el-select

        v-model="state.input"

        :loading="loading"

        loading-text="数据加载中..."

        filterable

        clearable

        popper-class="event-select-poper"

        v-el-select-loadmore="loadmore"

        placeholder="请输入属性值"

        style="width: 100%"

        :filter-method="filterOptions"

        @change="handleEventsChange"

        @visible-change="handleVisibleChange">

        <el-option

            v-for="item in dataList"

            :key="item.id"

            :label="item.name"

            :value="item.name">

        </el-option>

        <div style="margin:10 auto; text-align: center; color:#ccc">----已到底----</div>

    </el-select>

</template>

<script setup>

import { ref, nextTick } from 'vue';

import axios from 'axios';

const emits = defineEmits(['change'])

const dataList = ref([]);  //渲染数据数组

let loading = ref(false)

const state = ref({input: '', val: ''});

const pageIndex = ref(1);

const scrollpSize = ref(10);

const scrollPages = ref(1);

// 自定义v-el-select-loadmore指令

const vElSelectLoadmore = {

    beforeMount(el, binding) {

        /**

         * vue2时:

         * el.querySelector('.el-select-dropdown .el-select-dropdown__wrap');

         * vue3时:

         * 在el-select给一个参数popper-class="event-select-poper"          

         * element-plus中el-select的选项是使用的popper.js生成的,无法直接获取

        */

        const selectDom = document.querySelector('.event-select-poper .el-select-dropdown__wrap')

        let loadMores = function() {

            /**

            * scrollHeight 获取元素内容高度(只读)

            * scrollTop 获取或者设置元素的偏移值,常用于, 计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.

            * clientHeight 读取元素的可见高度(只读)

            * 如果元素滚动到底, 下面等式返回true, 没有则返回false:

            * ele.scrollHeight - ele.scrollTop === ele.clientHeight;

            */

            // 判断是否到底

            const isBase = this.scrollHeight - this.scrollTop <= this.clientHeight + 20

            if (isBase) {

                // 增加防抖

                binding.value && binding.value()

            }

        }

        // 将获取到的dom和函数挂载到el-select上,实例销毁时好处理

        el.selectDomInfo = selectDom

        el.selectLoadMore = loadMores

        // 监听滚动事件

        selectDom?.addEventListener('scroll', loadMores.bind(selectDom))

    },

    // 实例销毁

    beforeUnmount(el) {

        if (el.selectLoadMore) {

            el.selectDomInfo.removeEventListener('scroll', el.selectLoadMore)

            delete el.selectDomInfo

            delete el.selectLoadMore

        }

    }

}

// onBeforeMount(async () => {

//     await loadEvents()

// })

loadEvents();

// 模拟懒加载

const loadmore = () => {

    // 数据加载完成之后,不需要再执行懒加载

    if (pageIndex.value >= scrollPages.value) { return }

    pageIndex.value++

    nextTick(() => {

        loading.value = true

        getList();

        loading.value = false

    })

}

function getList() {

    axios({

        method: 'post',

        url: 'https://xxx.xx.x.xxx/dataSource/list',

        data: { name : state.value.val, pageIndex: pageIndex.value, pageSize: scrollpSize.value },

        headers: {'Content-Type': 'application/json;charset=UTF-8'}

    }).then(res => {

        let resdata = res.data && res.data.data || res.data;

        let respage = res.page || (res.data && res.data.page);

        for (let index = 0; index < resdata.length; index++) {

            dataList.value.push({ name:resdata[index].name, id:resdata[index].id });

        }

        scrollPages.value = respage.totalPage;

        pageIndex.value = respage.pageIndex;

    });

  }

// 自定义过滤函数

const filterOptions = (query = '') => {

    pageIndex.value = 1

    nextTick(async () => {

        dataList.value = [];

        state.value.val = query;

        getList();

    })

}

// 下拉框隐藏时,重置分页已经过滤得到的列表

const handleVisibleChange = (visible) => {

    if(!visible){

        pageIndex.value = 1;

    }

}

// 获取事件列表

function loadEvents () {

    loading.value = true;

    getList();

    // 调用接口

    loading.value = false;

}

const handleEventsChange = (val) => {

    console.log(val);

    emits('change', val)

}

</script>

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐