1、首先创建文件loadmore-select.vue
<template>
<el-select v-model="seVal"
:value-key="beforOptions.k"
filterable
remote
:remote-method="remoteFilter"
:placeholder="beforOptions.placeholderVal"
:clearable="beforOptions.clearable"
v-load-more="loadMore"
:default-first-option="true"
@change="onChange($event)"
@visible-change="visibleChange"
:disabled="beforOptions.disabled"
@remove-tag="removeTag"
>
<el-option v-for="(item,i) in loadData"
:key="beforOptions.k+item[beforOptions.k]+i"
:label="item[beforOptions.l]"
:value="beforOptions.bindingObj ? item :item[beforOptions.k]"
>
<span v-if="beforOptions.isDel" style="float: left">{{ item[beforOptions.l] }}</span>
<span v-if="beforOptions.isDel" style="float: right; color: #8492a6; font-size: 13px" @click.stop="deletePayees(item)">X</span>
</el-option>
<div class="load-more">
<label v-if="finished">到底啦</label>
<label v-else >滚动加载更多</label>
</div>
</el-select>
</template>
<script>
import service from '../searver';
const debounce = require('lodash.debounce');
export default {
props: {
echoData: [String],
// 额外参数
params: [Object],
// 手动配置项
options: [Object],
value: [String, Number, Object] // 默认值
},
// 这里使用computed 拦截v-model
computed: {
seVal: {
get(){
return this.value;
},
set(v) {
return this.$emit('input', v);
}
}
},
data () {
return {
// 默认配置项
beforOptions: {
isDel: false, // 是否删除项
k: 'id', // key值
l: 'name', // label值
bindingObj: false, // value绑定的值
placeholderVal: '请选择', // 提示文字
clearable: true, // 是否可清空
disabled: false, // 是否禁用
pageNum: 1,
pageSize: 10,
url: '' // 请求地址
},
loadData: [],
finished: false,
filterArray: [] // 所有可展示的数据 (符合搜索条件 && newData没有的数据)
};
},
created () {
// 初始化配置项
this.beforOptions = Object.assign(this.beforOptions, this.options);
},
mounted(){
if(this.echoData) {
this.remoteFilter(this.echoData);
}else{
this.loadMore();
}
},
methods: {
loadMore(){
// 禁止重复请求
if(this.finished){
return;
}
let data = {
pageNum: this.beforOptions.pageNum++,
pageSize: this.beforOptions.pageSize,
...this.params
};
service.getTableList(this.beforOptions.url, data).then(({code, data}) => {
if(code === 0){
if(data && data.records && data.records.length > 0){
this.loadData.push(...data.records);
}
// 判断是否到底
this.finished = !data || (data.current === data.pages);
}
});
},
visibleChange(v){
if(v && this.seVal){
this.remoteFilter('');
}
},
remoteFilter: debounce(function (v) {
// 当加载完毕时 直接退出方法
this.beforOptions.pageNum=1;
this.loadData = [];
this.finished = false;
this.params[this.beforOptions.l] = v;
this.loadMore();
}, 500,
{
leading: true,
trailing: false
}),
onChange(data){
this.$emit('onChange', data);
},
// 多选模式下 移除tag 触发
removeTag(data){
this.$emit('removeTag', data);
},
clearVal(){
this.seVal = '';
},
// 下拉框删除事件
deletePayees(data){
this.$emit('deletePayees', data);
}
},
// 组件销毁 重新加载
destroyed(){
this.loadData = [];
}
};
</script>
<style lang="scss" scoped>
div label {
font-size: 12px;
text-overflow: ellipsis;
color: #969696;
height: 34px;
line-height: 34px;
box-sizing: border-box;
}
.load-more{
width: 100%;
height: 34px;
line-height: 34px;
text-align: center;
color: #969696;
}
</style>
这里使用的是v-load-more指令,如图
export default {
bind(el, binding) {
const root = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap');
const dropdownDom = el.querySelector('.load-more');
// 创建一个IntersectionObserver实例
const observer = new IntersectionObserver((entries) => {
// 检查是否有元素进入视口
entries.forEach(entry => {
if (entry.isIntersecting) {
// 调用绑定的方法
binding.value();
}
});
}, {
root, // 相对于元素本身进行观察
rootMargin: '0px',
threshold: 1.0 // 当元素100%进入视口时触发
});
observer.observe(dropdownDom);
}
};
接下来就是使用方法
<loadmmoreSelect
class="ipt"
v-model="viewMb.task[index].assignee"
:echoData="viewMb.task[index].assigneeName"
:options="{
k:'roleId',
l:'roleName',
placeholderVal:'请选择审批角色',
url:'system/page'
}"
:params="{
districtId:currentUser.districtInfo.districtId,
roleKey: 'approve'
}"
/>