基于element-ui的el-select实现的下拉分页组件
<template>
<div>
<el-select
v-model="selectOption"
:value="value"
v-bind="$attrs"
:remote-method="remoteSearch"
:loading="loadings"
loading-text="加载中..."
@change="handleChange"
@visible-change="visibleChange"
>
<div v-infinite-scroll="loadScroll">
<el-option
v-for="item in dataList"
:key="item[valueName]"
:value="item[valueName]"
:label="item[labelName]"
/>
</div>
</el-select>
</div>
</template>
<script>
import request from '@/utils/request'
export default {
props: {
// 输入的值
value: {
type: [String, Array, Number],
default: null
},
// 请求的url
url: {
type: String,
default: ''
},
// value值的名称,默认值value
valueName: {
type: String,
default: 'value'
},
// label值的名称,默认值text
labelName: {
type: String,
default: 'text'
},
// 配置的请求参数
requestParam: {
type: Object,
default: () => {
return {}
}
},
// 回显的数据
visibleOption: {
type: Array,
default: () => {
return []
}
}
},
data() {
return {
dataList: [], // 获取的列表数据
selectOption: '', // 输入框的值
pagination: { // 分页参数
curPage: 0,
pageSize: 15
},
noMore: false, // 是否有下一页
queryKeyword: '', // 搜索的关键词
loadings: false // 加载的loading
}
},
watch: {
// 输入的值
value: {
handler(value) {
this.selectOption = value || ''
},
immediate: true
},
// 回显的值变化
visibleOption: {
handler(value) {
this.dataList = value
},
immediate: true
}
},
methods: {
// 获取列表数据
getList(value) {
this.loadings = true
this.queryKeyword = value || ''
request.post(this.url, {
queryKeyword: this.queryKeyword,
...this.pagination,
...this.requestParam
}).then(({ flag, data: { dataList, totalRows }}) => {
if (flag === 1) {
if ((this.pagination.curPage * this.pagination.pageSize + dataList.length) < totalRows) {
this.dataList = this.dataList.concat(dataList)
this.noMore = false
} else if ((this.pagination.curPage * this.pagination.pageSize + dataList.length) === totalRows) {
this.dataList = this.dataList.concat(dataList)
this.noMore = true
} else {
this.noMore = true
}
// 去重
if (this.visibleOption.length) {
this.dataList = [...this.visibleOption, ...this.dataList]
const map = new Map()
const list = []
this.dataList.forEach((item) => {
if (map.has(item[this.valueName])) {
map.set(item[this.valueName], true)
} else {
map.set(item[this.valueName], false)
list.push(item)
}
})
this.dataList = list
}
}
this.loadings = false
})
},
// 选中的值变化
handleChange(data) {
this.$emit('input', data)
this.$emit('change', data)
},
// 远程搜索方法
remoteSearch(value) {
this.dataList = []
this.noMore = false
this.pagination.curPage = 0
this.getList(value)
},
// 下拉框出现时
visibleChange(visible) {
if (!visible) {
this.queryKeyword = ''
this.noMore = false
this.dataList = []
this.pagination.curPage = 0
} else {
this.getList(this.queryKeyword)
}
},
// 滚动获取数据
loadScroll() {
if (!this.noMore) {
this.pagination.curPage++
this.getList(this.queryKeyword)
}
}
}
}
</script>