赞
踩
当下拉选择器含大量的数据时,影响性能问题,因而以懒加载的方式作为性能优化;
该下拉选择器包含功能:物理搜索、触底懒加载、适用单选和多选;
其中要点:
<template>
<yh-select v-model="selectVal" placeholder="请选择" filterable clearable :data-class="className" :popper-class="className" v-selectScroll="scrollChange" :filter-method="filtereMethod" :multiple="multiple" collapse-tags collapse-tags-tooltip :reserve-keyword="false" @change="changeVal">
<yh-option v-for="(item, index) in selectParams.showData" @click="clickOption(item.value)" :key="index" :value="item.value" :label="item.label" :title="item.label" />
</yh-select>
</template>
const props = defineProps({ value: { default: null }, optionsData: { default: [] }, className: { default: 'lazyselect' }, multiple: { default: false }, }); const emit = defineEmits(['returnValue']); let selectVal = ref(); //默认下拉的分页数 let defaultPageNum = ref(200); //下拉参数 let selectParams = ref({ pageSize: 1,//当前页码 pageNumber: defaultPageNum.value,//默认显示条数 allData: [],//全部数据 showData: [],//展示数据 activeFilter: false,//搜索状态 }); //下拉选中值监听 watch( () => props.value, (to, from) => { selectVal.value = to; addValueSelect(); } ); onMounted(() => { selectParams.value = { pageSize: 1, pageNumber: defaultPageNum.value, total: 0, allData: props.optionsData || [], showData: props.optionsData?.length ? props.optionsData?.slice(0, props.optionsData.length < defaultPageNum.value ? props.optionsData.length : defaultPageNum.value) : [], activeFilter: false, }; addValueSelect(); selectVal.value = props.multiple ? selectVal.value?.split(',') || [] : selectVal.value || ''; }); //点击选项,非多选时执行 const clickOption = (e) => { if (!props.multiple) { selectParams.value.activeFilter = false; selectVal.value = e; emit('returnValue', selectVal.value); } }; //添加已选的下拉选项 const addValueSelect = () => { const value = selectVal.value; if (![null, undefined].includes(value) && value !== '' && !selectParams.value.showData?.find((i) => i.value == value) && selectParams.value.allData.length) { const item = selectParams.value.allData.find((i) => i.value === value); if (item) { selectParams.value.showData.push(item); } } }; //滚动下拉 const scrollChange = () => { const { allData, showData, pageNumber } = selectParams.value; if (showData.length < allData.length && !selectParams.value.activeFilter) { selectParams.value.pageSize += 1; const addData = selectParams.value.pageSize * pageNumber; selectParams.value.showData = addData > allData.length ? allData : allData.slice(0, addData); } addValueSelect(); }; //下拉搜索 const filtereMethod = (e) => { const { allData, showData } = selectParams.value; if (e !== '') { if (!props.multiple) { selectVal.value = e; } const filterArr = allData.filter((i) => i.label.toLowerCase().includes(e?.toLowerCase())); selectParams.value.showData = filterArr; selectParams.value.activeFilter = true; } else { selectParams.value.showData = reSetOptions(allData.slice(0, defaultPageNum.value).concat(showData), 'value'); if (selectParams.value.activeFilter) { changeVal(e); } selectParams.value.activeFilter = false; } }; //数组去重 const reSetOptions = (arr, name) => { let obj = {}; return arr.reduce((cur, next) => { obj[next[name]] ? '' : (obj[next[name]] = true && cur.push(next)); return cur; }, []); }; //下拉值修改 const changeVal = (e) => { selectParams.value.activeFilter = false; selectVal.value = e; emit('returnValue', selectVal.value); };
代码要点解析:
select触底指令:
import type { Directive, DirectiveBinding } from 'vue'; //下拉滚动触底监听指令 const selectScroll: Directive = { mounted(el, binding) { const className = `.${el.dataset.class}`, element = document.querySelector(className)?.querySelector(".el-select-dropdown .el-select-dropdown__wrap"); element?.addEventListener("scroll", () => { scrollSelect(element, binding); }) }, beforeUnmount(el, binding) { const className = `.${el.dataset.class}`, element = document.querySelector(className)?.querySelector(".el-select-dropdown .el-select-dropdown__wrap"); element?.removeEventListener("scroll", () => { scrollSelect(element, binding); }) } } const scrollSelect = (element, binding) => { const { scrollTop, scrollHeight, clientHeight } = element, scrollDistance = scrollHeight - scrollTop - clientHeight; if (scrollDistance <= 0) { binding.value(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。