通过vue-virtual-scroller封装虚拟滚动el-select

张开发
2026/4/13 1:34:09 15 分钟阅读

分享文章

通过vue-virtual-scroller封装虚拟滚动el-select
通过vue-virtual-scroller封装虚拟滚动el-select组件的代码。该组件解决了大量数据渲染时的性能问题支持普通列表和分组列表两种虚拟滚动模式组件内容!--使用文档 https://blog.csdn.net/weixin_49455560/article/details/160083586?spm1011.2415.3001.5331--template typetext/x-templateidvirtual-selectel-select:sizesizev-modelvalue:loadingloadingchangehandleChangefocushandleFocusblurhandleBlur:multiplemultiple:filterablefilterable:filter-methodhandleFilterMethodvisible-changehandleVisibleChange:disableddisabled:collapse-tagscollapseTags:placeholderplaceholder:clearableclearable!--begin 普通下拉--recycle-scroller v-iftype 1:itemsfilteredItems:item-sizeitemSize:key-fieldprops.valuestylemax-height: 250pxtemplate v-slot:default{item, index}el-option:labelitem[props.label]:valueitem[props.value]:keyitem[props.value]slot namedefault:itemitem/slot/el-option/templatetemplate #empty v-if!filteredItems.lengthdivclassempty-txt暂无数据/div/template/recycle-scroller!--end 普通下拉--!--begin 分组下拉--dynamic-scroller v-iftype 2:itemsfilteredGroupItems:min-item-sizegroupItemSize:key-fieldprops.groupIdstylemax-height: 250pxtemplate v-slot{ item, index, active }dynamic-scroller-item:itemitem:activeactive:size-dependencies[ item[props.children] || [] ]:data-indexindexel-option-group v-ifitem[props.children].length 0:labelitem[props.group]:keyitem[props.groupId]el-option v-for(citem, cindex) in item[props.children] || []:keycitem[props.value]:labelcitem[props.label]:valuecitem[props.value]slot namedefault:itemcitem/slot/el-option/el-option-group/dynamic-scroller-item/templatetemplate #empty v-if!filteredGroupItems.lengthdivclassempty-txt暂无数据/div/template/dynamic-scroller!--end 分组下拉--/el-select/templatelink relstylesheethref/assets/js/vue-virtual-scroller/vue-virtual-scroller.css/script src/assets/js/vue-virtual-scroller/vue-virtual-scroller.min.js/scriptscriptVue.component(recycle-scroller,VueVirtualScroller.RecycleScroller);Vue.component(dynamic-scroller,VueVirtualScroller.DynamicScroller);Vue.component(dynamic-scroller-item,VueVirtualScroller.DynamicScrollerItem);Vue.component(virtual-select,{template:#virtual-select,model:{prop:value,event:change,},props:{type:{type:Number,default:1,// 1-普通虚拟下拉 2-分组虚拟下拉},value:{type:[String,Array],required:true,},loading:{type:Boolean,default:false,},items:{type:Array,default:[],},multiple:{type:Boolean,default:false,},filterable:{type:Boolean,default:false,},filterMethod:{type:Function,default:null,},clearable:{type:Boolean,default:false,},placeholder:{type:String,default:请选择,},size:{type:String,default:mini,},disabled:{type:Boolean,default:false,},collapseTags:{type:Boolean,default:false,},// 单行高度pxitemSize:{type:Number,default:34,},// 分组项最小高度pxgroupItemSize:{type:Number,default:64,},// 自定义属性名称props:{type:Object,default:(){return{group:group,// 分组名称groupId:groupId,// 分组idlabel:label,// 选项名称value:value,// 选项值children:children,// 子数据};},},},computed:{// 过滤后的普通列表数据filteredItems(){if(!this.filterable||!this.query||this.filterMethod){returnthis.items;}constlabelFieldthis.props.label;returnthis.items.filter(itemString(item[labelField]).toLowerCase().includes(this.query.toLowerCase()));},// 过滤后的分组列表数据filteredGroupItems(){if(!this.filterable||!this.query||this.filterMethod){returnthis.items.filter(groupgroup[this.props.children]group[this.props.children].length);}constlabelFieldthis.props.label;constchildrenFieldthis.props.children;constkeywordthis.query.toLowerCase();returnthis.items.map(group{constfilteredChildren(group[childrenField]||[]).filter(childString(child[labelField]).toLowerCase().includes(keyword));return{...group,[childrenField]:filteredChildren,};}).filter(groupgroup[this.props.children]group[this.props.children].length);},},data:(){return{query:,};},methods:{// 过滤方法handleFilterMethod(val){this.queryval;if(this.filterMethod){this.filterMethod(this.query);}},// 选择方法handleChange(val){this.$emit(change,val);},// 可见性改变方法handleVisibleChange(visible){if(visible){this.query;}this.$emit(visible-change,visible);},// 聚焦方法handleFocus(){this.$emit(focus,this);},// 失焦方法handleBlur(){this.$emit(blur,this);},},});/scriptstyle.empty-txt{line-height:32px;text-align:center;color:#999;}/style基础用法普通列表templatevirtual-select v-modelselectedValue:type1:itemsoptionsplaceholder请选择filterable clearable/virtual-select/templatescriptexportdefault{data(){return{selectedValue:,options:Array.from({length:10000},(_,i)({label:选项${i1},value:i1}))}}}/script分组列表用法templatevirtual-select v-modelselectedValue:type2:itemsgroupOptionsplaceholder请选择分组filterable/virtual-select/templatescriptexportdefault{data(){return{selectedValue:,groupOptions:Array.from({length:200},(_,i){return{group:分组${i1},groupId:i1,children:Array.from({length:3},(_,j)({label:选项${i1}${j300},value:${i1}${j300},})),};}),}}}/scriptAPI 文档Props参数说明类型默认值type类型1-普通虚拟下拉2-分组虚拟下拉Number1value绑定值支持 v-modelString / Array必填loading是否显示加载中状态Booleanfalseitems数据源Array[]multiple是否多选Booleanfalsefilterable是否可搜索Booleanfalsefilter-method自定义过滤方法Functionnullclearable是否可清空Booleanfalseplaceholder占位符String请选择size尺寸Stringminidisabled是否禁用Booleanfalsecollapse-tags多选时是否折叠标签Booleanfalseitem-size普通列表单行高度pxNumber34group-item-size分组列表最小高度pxNumber64props字段映射配置Object见下方说明props 默认值{group:group,// 分组名称字段groupId:groupId,// 分组ID字段label:label,// 选项名称字段value:value,// 选项值字段children:children// 子数据字段}Events事件名说明回调参数change值变化时触发当前选中的值focus获得焦点时触发(event: Event)blur失去焦点时触发(event: Event)visible-change下拉框显示/隐藏时触发visible是否显示

更多文章