方式一 下拉滚动加载
用于分页数据的懒加载 vue+elment
新建elSelct.vue 组件
<template>
<div>
<el-select v-el-select-loadmore="loadMore" :value="defaultValue" :loading="loading" :multiple="multiple"
:placeholder="placeholder" :allow-create="allowCreate" filterable remote clearable
:remote-method="(query) => {remoteMethod(query, value)}" style="width: 100%;" @change="change"
@input="$emit('input',$event)" @visible-change="visibleChange" @clear="clearChange">
<el-option v-if="hasAll" :label="defaultLabel" value="" />
<el-option v-for="(item,index) in optionsList" :key="item.index+'s'+item.id"
:label="concatString2(item[label], item[labelTwo])" :value="item[valueString]">
{{ concatString(item[label], item[labelTwo]) }}</el-option>
</el-select>
</div>
</template>
<script>
export default {
name: 'YSelect',
directives: {
'el-select-loadmore': {
bind(el, binding) {
// 获取element-ui定义好的scroll盒子
const DOM = el.querySelector('.el-select-dropdown .el-select-dropdown__wrap')
DOM.addEventListener('scroll', function() {
/**
* scrollHeight 获取元素内容高度(只读)
* scrollTop 获取或者设置元素的偏移值,常用于, 计算滚动条的位置, 当一个元素的容器没有产生垂直方向的滚动条, 那它的scrollTop的值默认为0.
* clientHeight 读取元素的可见高度(只读)
* 如果元素滚动到底, 下面等式返回true, 没有则返回false:
* ele.scrollHeight - ele.scrollTop === ele.clientHeight;
*/
const condition = this.scrollHeight - this.scrollTop <= this.clientHeight
if (condition) {
binding.value()
}
})
}
}
},
props: {
// 是否允许创建条目
allowCreate: {
type: Boolean,
default: false
},
// 需要显示的名称
label: {
type: String,
default: ''
},
// 需要显示的名称
labelTwo: {
type: String,
default: ''
},
// 传入的数据,必填
value: {
type: [String, Number, Array],
default: null
},
// 是否拼接label | value
isConcat: {
type: Boolean,
default: false
},
isConcatShowText: {
type: Boolean,
default: false
},
// 拼接label、value符号
concatSymbol: {
type: String,
default: ' | '
},
valueString: {
type: String,
default: ''
},
// 选项数据,必填
options: {
type: Array,
default: () => {
return []
}
},
// 是否有全部选项
hasAll: {
type: Boolean,
default: true
},
defaultLabel: {
type: String,
default: '全部'
},
// 加载loading
loading: {
type: Boolean,
default: false
},
// 提示
placeholder: {
type: String,
default: '请选择'
},
// 是否支持多选
multiple: {
type: Boolean,
default: false
},
// 每次显示数量
size: {
type: Number,
default: 100
}
},
data() {
return {
page: 1,
pageRemote: 1,
defaultLoading: false,
timer: null,
optionsList: [],
oldOptions: [],
isRemote: false,
defaultValue:null,
}
},
watch: {
options: {
handler(val) {
if (this.isRemote) {
if (val) {
this.optionsList = val
this.oldOptions = this.oldOptions.filter((item) => {
return !val.some(valItem => item.id === valItem.id)
})
this.oldOptions = [...this.oldOptions, ...val]
}
} else {
if (val) {
this.optionsList = this.optionsList.filter((item) => {
return !val.some(valItem => item.id === valItem.id)
})
this.optionsList = [...this.optionsList, ...val]
}
}
},
deep: true
},
value: {
handler(val, oldVal) {
this.defaultValue = this.value
if (val==='null' || val===null || val==='undefined' || val===undefined || val===''){
this.clearChange()
}
},
immediate: false,
deep: true
}
},
mounted() {
this.defaultValue = this.value
this.optionsList = this.options
},
methods: {
//选择后 只显示label
//张三
concatString(a, b) {
a = a || ''
b = b || ''
if (this.isConcat) {
// return a + ((a && b) ? ' | ' : '') + b
return a + ((a && b) ? this.concatSymbol : '') + b
}
return a
},
//选择下拉展示时 可以展示label和labelTwo
//123||张三
concatString2(a, b) {
a = a || ''
b = b || ''
if (this.isConcat) {
// return a + ((a && b) ? ' | ' : '') + b
if (this.isConcatShowText == true) {
return a + ((a && b) ? this.concatSymbol : '') + b
} else {
return a
}
}
return a
},
change(val) {
console.log('change', val)
this.$emit('change', val)
},
visibleChange(status) {
console.log('change2', status)
if (!status) {
if (this.isRemote) {
this.isRemote = false
this.optionsList = [...this.oldOptions]
}
}
this.$emit('visibleChange', status)
},
loadMore() {
console.log(this.isRemote, this.pageRemote, this.page)
if (this.isRemote) {
if (this.pageRemote === 1) {
this.$emit('loadMore', this.pageRemote)
this.pageRemote++
} else {
this.pageRemote++
this.$emit('loadMore', this.pageRemote)
}
} else {
this.page++
this.$emit('loadMore', this.page)
}
},
remoteMethod(query) {
this.pageRemote = 1
if (this.timer) {
clearTimeout(this.timer)
this.timer = null
}
this.timer = setTimeout(() => {
this.isRemote = true
this.oldOptions = [...this.optionsList]
this.optionsList = []
this.$emit('remoteMethod', query, this.pageRemote)
}, 500)
},
//清除
clearChange() {
if (typeof this.defaultValue === 'string') {
this.defaultValue = ''
} else if (this.isMultiple) {
this.defaultValue = []
}
this.$emit('clear')
}
}
}
</script>
<style lang='scss' scoped>
</style>
然后再页面引用
hasAll 是否显示全部2个字 is-concat 是否拼接 concat-symbol拼接符号 is-multiple是否多选 label 字段名称1 labelTwo 字段名称2 valueString要获取的value值,是id还是projectCode options显示的数据 @loadMore加载更多 的方法 @remoteMethod远程请求的方法 @change方法
[{name:'我是名称’,projectCode:‘0121’,id:1}]
<template>
<YSelect v-model="form.contractNumber" :hasAll='false' :is-concat="true" :is-multiple="false"
:isConcatShowText="false" :concat-symbol="' || '" label="name" labelTwo="projectCode" valueString="id"
:options="contractList" :placeholder="'请选择合同编号'" @loadMore="loadMore" @remoteMethod="remoteMethod"
@change="selectContract" @clear='contractClear()'/>
</template>
import YSelect from '@/views/components/elSelect/index'
export default {
components: {YSelect},
data:{
return(){
projectPageNum:0
}
},
mounted() {
this.projectSearch()
},
methods: {
//清除
contractClear(){},
//下拉框选中完成后
visibleChange(status) {},
//下拉框改变时
selectChange(){},
//项目号 懒加载 下拉加载更多
loadMore(page) {
let that=this
that.projectPageNum =page
this.projectSearch('',true)
},
//项目号 下拉框的远程搜索
remoteMethod(query, page) {
this.projectPageNum = page
this.projectSearch(query,false)
},
/**项目号搜索 列表展示*/
projectSearch(val, lazy = false) {
let that = this
if (lazy == false) { // 如果不是懒加载,
this.projectList = [] // 把select选项数组重置为空
that.projectPageNum = 1 // 设置查询第一页,每页20条
}
//请求后台数据
listInfo({
search: val,
pageSize: 30,
pageNum: that.projectPageNum
}).then(response => {
that.projectList=response.rows
});
},
}
}
方式二 点击分页加载
<el-select v-model="form.goodsName" placeholder="请选择" style="width: 100%"
filterable remote clearable :remote-method="goodsSearchQuery"
:popper-append-to-body="true" popper-class="select-dropdown"
@visible-change="goodsVisibleChange" @change="setGoodInfo($event,scope.$index)">
<el-option v-for="item in goodsList" :key="item.id" :label="item.name" :value="item.id">{{item.name+' || '+item.productCode+' || '+item.typeName+' || '+item.model}}</el-option>
<el-pagination class="select-pagination" @size-change="goodsSizeChange"
@current-change="goodsCurrentChange" :current-page.sync="goodsPageNum"
:page-size="goodsPageSize" :pager-count="10" :small="true"
:total="goodsTotal" layout="prev, pager, next, total">
</el-pagination>
</el-select>
<script>
export default {
data() {
return {
form: {
goodsName: undefined,
goodsNumber :undefined,
goodsId:undefined
},
goodsList: [],
goodsPageNum: 0,
goodsTotal: 0,
goodsPageSize: 6,
goodsSelectedValue:null
}
},
created() {
this.goodsSearchQuery() //产品列表
},
methods: {
/**搜索产品*/
goodsSearchQuery(queryVal) {
let that = this
this.goodsSelectedValue = queryVal;
//请求的数据
listGoods({
search: queryVal,
pageSize: that.goodsPageSize,
pageNum: that.goodsPageNum
}).then(response => {
//每次进入后 数据都是重新填充
that.goodsList = response.rows;
that.goodsTotal = response.total;
});
},
/**点击下拉框 下拉框隐藏和显示时*/
goodsVisibleChange(visible) {
if (visible) {
this.goodsPageNum = 1;
this.goodsSearchQuery(""); // 下拉框打开时触发查询
}
},
/*分页时调用方法*/
goodsSizeChange(size) {
this.goodsPageSize = size;
this.goodsSearchQuery(this.goodsSelectedValue);
},
goodsCurrentChange(page) {
this.goodsPageNum = page;
this.goodsSearchQuery(this.goodsSelectedValue);
},
/**获取产品详情设置**/
setGoodInfo(val, index) {
if (val) {
getGoods(val).then(response => {
this.form.goodsId = val
this.form.goodsName = response.data.name
this.form.goodsNumber = 1
})
}
},
}
}
</script>
请求的数据格式
[
{
“createBy”: “xx”,
“createTime”: “2023-06-21 17:06:05”,
“updateTime”: “2024-04-17 10:58:38”,
“id”: 1,
“productCode”: “70700460”,
“name”: “氨氮水质自动在线监测仪”,
“nameAndCode”: “氨氮水质自动在线监测仪-70700460”,
“model”: “BEW-AN100(V2.6_0200)”,
“type”: 1,
“typeName”: “污染源”,
“unit”: “台”,
“salesPrice”: 36000,
“notes”: “”,
“classify”: 5,
“ledgerCode”: null,
“search”: null
}
]
本文章仅仅用于记录,便于后续查看