select懒加载解决el
需求:在一个dialog中使用了多个el-select提供选择用户、角色、部门等入口,但是每次打开弹框的时候都需要等很久才能将已选数据回显出来,而且在页面加载完成前鼠标无法操作dailog
解决方案:
- 请求接口先获取到所有的option数组
- 首次只截取10条option数据,避免option过多导致页面卡顿
- 监听下拉框滚动事件,用户打开下拉框并滚动到下拉框底部后截取1-20条数据,以此类推
- 考虑到需要回显的老数据,在截取数据后从所有option数组中找到已选的用户并unshift进去(如果截取的option中有已选数据就不用)
实现步骤:
先自定义一个监听select下拉框滚动的指令,通过
export default {mounted(el, { arg, value }) {const SELECTWRAP_DOM = document.querySelector(`.${arg} .el-select-dropdown__wrap`);SELECTWRAP_DOM &&SELECTWRAP_DOM.addEventListener("scroll", function () {const condition =SELECTWRAP_DOM.scrollHeight - SELECTWRAP_DOM.scrollTop ==SELECTWRAP_DOM.clientHeight;if (condition && SELECTWRAP_DOM.scrollTop > 0) {value();}});},
};
main.js中全局注册这个自定义指令
import selLazyLoad from '@/directive/common/selLazyLoad'app.directive('selLazyLoad', selLazyLoad)
html结构:
<el-selectv-model="libyModel.user"multiplefilterablev-selLazyLoad:[arg]="loadMore":popper-class="arg":filter-method="userFilterMethod":reserve-keyword="false"placeholder="请选择"style="width: 100%"@change="changeLibyOpts('user')"><el-optionv-for="item in userOptList":key="item.userId":label="item.nickName":value="item.userId":disabled="item.disabled">{{ item.nickName }}</el-option></el-select>
定义方法:
const loadMore = () => {// 如果截取的长度==获取到的所有option长度将不再截取if (userOptList.value.length == userOptions.value?.length) return;userPageNum.value++;getScrollUser();
};// 截取页面显示的实际option
const getScrollUser = () => {// 过滤出前十条用户信息+需要回显的数据userOptList.value = userOptions.value.slice(0, userPageNum.value * 10);if (libyModel.value.user?.length && userOptList.value?.length)libyModel.value.user.forEach((item) => {let hasOpt = userOptList.value.findIndex((val) => val.userId === item);if (hasOpt > -1) return;let findItem = userOptions.value.find((val) => val.userId === item);findItem &&userOptList.value.unshift({...findItem,});});
};// 搜索功能
const userFilterMethod = (value) => {// 手动触发下拉框回滚至顶部,避免触发v-slLazyLoad指令document.querySelector(`.${props.arg} .el-select-dropdown__wrap`).scrollTop = 0;if (!value?.length) return getScrollUser();userOptList.value =userOptions.value.filter((item) => item.nickName?.includes(value)) || [];
};
select懒加载解决el
需求:在一个dialog中使用了多个el-select提供选择用户、角色、部门等入口,但是每次打开弹框的时候都需要等很久才能将已选数据回显出来,而且在页面加载完成前鼠标无法操作dailog
解决方案:
- 请求接口先获取到所有的option数组
- 首次只截取10条option数据,避免option过多导致页面卡顿
- 监听下拉框滚动事件,用户打开下拉框并滚动到下拉框底部后截取1-20条数据,以此类推
- 考虑到需要回显的老数据,在截取数据后从所有option数组中找到已选的用户并unshift进去(如果截取的option中有已选数据就不用)
实现步骤:
先自定义一个监听select下拉框滚动的指令,通过
export default {mounted(el, { arg, value }) {const SELECTWRAP_DOM = document.querySelector(`.${arg} .el-select-dropdown__wrap`);SELECTWRAP_DOM &&SELECTWRAP_DOM.addEventListener("scroll", function () {const condition =SELECTWRAP_DOM.scrollHeight - SELECTWRAP_DOM.scrollTop ==SELECTWRAP_DOM.clientHeight;if (condition && SELECTWRAP_DOM.scrollTop > 0) {value();}});},
};
main.js中全局注册这个自定义指令
import selLazyLoad from '@/directive/common/selLazyLoad'app.directive('selLazyLoad', selLazyLoad)
html结构:
<el-selectv-model="libyModel.user"multiplefilterablev-selLazyLoad:[arg]="loadMore":popper-class="arg":filter-method="userFilterMethod":reserve-keyword="false"placeholder="请选择"style="width: 100%"@change="changeLibyOpts('user')"><el-optionv-for="item in userOptList":key="item.userId":label="item.nickName":value="item.userId":disabled="item.disabled">{{ item.nickName }}</el-option></el-select>
定义方法:
const loadMore = () => {// 如果截取的长度==获取到的所有option长度将不再截取if (userOptList.value.length == userOptions.value?.length) return;userPageNum.value++;getScrollUser();
};// 截取页面显示的实际option
const getScrollUser = () => {// 过滤出前十条用户信息+需要回显的数据userOptList.value = userOptions.value.slice(0, userPageNum.value * 10);if (libyModel.value.user?.length && userOptList.value?.length)libyModel.value.user.forEach((item) => {let hasOpt = userOptList.value.findIndex((val) => val.userId === item);if (hasOpt > -1) return;let findItem = userOptions.value.find((val) => val.userId === item);findItem &&userOptList.value.unshift({...findItem,});});
};// 搜索功能
const userFilterMethod = (value) => {// 手动触发下拉框回滚至顶部,避免触发v-slLazyLoad指令document.querySelector(`.${props.arg} .el-select-dropdown__wrap`).scrollTop = 0;if (!value?.length) return getScrollUser();userOptList.value =userOptions.value.filter((item) => item.nickName?.includes(value)) || [];
};