使用方法<el-form-itemclass="form-condition":label="$t('privacyPolicy.userId')"prop="userNo"><LoadMoreSelectv-model="detailForm.userNo":fetchOptions="fetchStockLocationUserNoData"keyField="value" labelField="label" valueField="value" :page="this.selectPage.pageIndex" :pageSize="this.selectPage.pageSize" /></el-form-item>import LoadMoreSelect from '@/components/LoadMoreSelect/LoadMoreSelect.vue';components: { LoadMoreSelect },methods: {async fetchStockLocationUserNoData({ pageIndex, pageSize, query }) {const response = await qryUserId({pageIndex,pageSize,info: query,isDeleted: 0 });return response;},
}
main.js
Vue.directive('loadmore', {bind(el, binding) {let select_dom = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap');select_dom.addEventListener('scroll', function () {const CONDITION = this.scrollHeight - this.scrollTop <= this.clientHeight;if (CONDITION) {binding.value();}});}
});
<template><el-selectv-model="internalValue":popper-append-to-body="false"@change="handleChange":placeholder="$t('placeholder.select')":loading="loading"v-loadmore="handleLoadMore"filterableremote:remote-method="(query) => loadOptions(page, pageSize, query, false)"><!-- @visible-change="visibleChange" --><el-optionv-for="item in options":key="item[keyField]":label="item[labelField]":value="item[valueField]"></el-option><ElSelectLoading :hasMore="hasMore" /></el-select>
</template><script>
import ElSelectLoading from './components/ElSelectLoading.vue';
export default {components: {ElSelectLoading},props: {value: {type: [String, Number],default: ''},placeholder: {type: String,default: ''},fetchOptions: {type: Function,required: true},keyField: {type: String,default: 'id'},labelField: {type: String,default: 'label'},valueField: {type: String,default: 'value'},page: {type: Number,default: 1},pageSize: {type: Number,default: 50}},data() {return {internalValue: this.value,options: [],loading: false,hasMore: false,total: 0,query: '',currentPage: 1};},watch: {value(newVal) {this.internalValue = newVal;},internalValue(newVal) {this.$emit('input', newVal);}},mounted() {},methods: {async loadOptions(page, pageSize, query, isloadmore) {if (query !== '') {this.query = query;if (!isloadmore) {this.loading = true;}try {const res = await this.fetchOptions({ page, pageSize, query });console.log(res, 'fetchOptions');const list = res.data || [];this.total = res.total;if (isloadmore) {this.options.push(...list);} else {this.options = list;}} catch (error) {console.error(error);} finally {this.loading = false;}}},handleLoadMore() {this.currentPage = this.currentPage + 1;if (this.currentPage > Math.ceil(this.total / 50)) {this.hasMore = false;return;}this.hasMore = true;this.loadOptions(this.currentPage, this.pageSize, this.query, true);},handleChange(value) {this.internalValue = value;this.$emit('change', value);}}
};
</script><style scoped lang="scss"></style>
<template><el-option ref="el" class="el-select-loading" value=""><template v-if="hasMore"><el-icon class="el-icon-loading"></el-icon><span class="el-select-loading__tips">{{ $t('common.loading') }}</span></template><template v-else>{{ $t('common.Nodata') }}</template></el-option>
</template><script>
export default {name: 'LoadMoreSelectOption',props: {hasMore: {type: Boolean,required: false}},data() {return {};},mounted() {},beforeDestroy() {},methods: {}
};
</script><style scoped lang="scss">
.el-select-loading {display: flex;align-items: center;justify-content: center;cursor: initial;pointer-events: none;background-color: rgb(255, 255, 255);color: #4d4d4d;font-size: 12px;&__icon {font-size: 16px;animation: rotate 1.5s linear infinite;}&__tips {margin-left: 6px;}@keyframes rotate {from {transform: rotate(0deg);}to {transform: rotate(360deg);}}
}
</style>