<>使用场景:
类似:表单中有需要选择的下拉框选项太多,选择的时候会因为数据量过大导致页面卡顿,于是对于el-select进行二次封装
<>解决方案:
* remote-method:远程搜索方法
* 创建 el-select-loadmore 指令方法进行滚动加载
<>组件代码:
value:数据绑定传入的数据
options:选项数据,必填
@visibleChange 下拉框出现/隐藏时触发
@loadMore 滚动加载触发
@remoteMethod 远程搜索触发
@change 选中值发生变化时触发
<template> <YSelect v-model="form.id" :options="list" :loading="loading"
:placeholder="'请选择xxx'" @visibleChange="visibleChange" @loadMore="loadMore"
@remoteMethod="remoteMethod" @change="change" /> </template> <script> import
YSelectfrom '@/components/ySelect' export default { components: { YSelect },
data: { return { form: { id: '' }, selectForm: { page: 1, size: 100, name: '' },
loading: false } }, methods: { init: async function() { this.loading = true //
获取选项数据,后端需支持 page size name搜索 const res = await getIdOptions({page: this.
selectForm.page, size: this.selectForm.size, name: this.select.name}) this.list
= res.data this.loading = false }, change(value) { }, visibleChange(status) {
this.select.name = '' }, loadMore(page) { this.selectForm.page = page this.init(
) }, remoteMethod(query, page) { this.selectForm.page = page this.select.name =
querythis.init() } } } </script>
<>组件代码:
<template> <div> <el-select v-el-select-loadmore="loadMore" :value="value"
:loading="loading" :multiple="multiple" :placeholder="placeholder" filterable
remote :remote-method="(query) => {remoteMethod(query, value)}" style="width:
100%;" @change="change" @input="$emit('input',$event)" @visible-change="
visibleChange" > <el-option v-if="hasAll" :label="defaultLabel" value="" /> <
el-option v-for="item in optionsList" :key="item.id" :label="item.name" :value="
item.id" /> </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: { //
传入的数据,必填 value: { type: [String, Number, Array], default: null }, // 选项数据,必填
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 } }, 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 } }, mounted() { this.optionsList = this.options }, methods: { change(val)
{ this.$emit('change', val) }, visibleChange(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)
} } } </script> <style lang='scss' scoped> </style>