以级联选择器为例,聊聊数据量过大造成的页面卡顿问题
前端小卡
共 4729字,需浏览 10分钟
·
2021-03-14 11:50
背景
❝列表、树、级联选择都是用来展示“大量”、“相似度高”的数据,它们都是需要在dom中生成大量的节点,这就造成了数据量大造成页面卡顿的原因,当然以elementui为例,其实el-tree和el-cascader都对外提供了允许数据懒加载提供了接口。还是以级联选择器为例,仅仅是提供了父节点到子节点的懒加载,若子节点数据量大,那就的需要我们自己来二次封装。下面就来简单实现一下这个二次封装的懒加载。下面实现的组件仅仅考虑子节点数据量大的情况
❞
效果展示
考虑因素
❝❞
我们暂时称一级菜单为「类型」,二级菜单为「标签」 初始化时,我们设置一个固定的标签个数n,如果每个类型大于等于n,则显示个数为n,如果小于n则显示已有的个数 当我们滚动条滚动到底部时,继续加载n个标签,直到加载完毕。 加载完新的数据之后,要让滚动条停留到上次滚动的位置 假如我们设置了默认全选,则要在懒加载的时候,加载出来的新标签也要设置为选择状态 尽管首次渲染仅仅加载了部分标签,但是允许搜索的时候,范围为所有的标签数据 全选的时候要有一个标识来告诉用户现在是全选的状态
关键代码
在触发每个「类型」的click时候,需要为级联面板绑定滚动监听,并将当前的类型传到滚动回调。当然因为回调函数为同一个,所以不会造成多次监听的问题。
handleChange(value) {
if (!this.lazy) {
return
}
this.$nextTick(() => {
const panel = document.querySelectorAll('.el-cascader-menu__wrap.el-scrollbar__wrap')
const length = panel.length
const currentPanel = panel[length-1]
this.type = value[0]
if (currentPanel) {
currentPanel.addEventListener('scroll', this.scrollCallback(currentPanel))
}
})
},
大部分的逻辑都在滚动回调中
scrollCallback(el) {
return () => {
const scrollTop = el.scrollTop
const clientHeight = el.clientHeight
const scrollHeight = el.scrollHeight
// 若scrollTop + clientHeight === scrollHeight 则说明滚动条到达了底部
if (scrollTop + clientHeight === scrollHeight) {
const tmp = []
// 当前类型下所有的选项
const allOptions = this.allOptions.filter(options=>options.value === this.type)[0]?.children
this.options.forEach(element => {
if (element.value === this.type) {
const optionLen = element.children.length-1
const allOptionsLen = allOptions.length-1
if (optionLen >= allOptionsLen) {
return
}
const loadsize = optionLen + this.loadSize
// 当我们滚动条滚动到底部时,继续加载n个标签,直到加载完毕
const size = loadsize > allOptionsLen ? allOptionsLen : loadsize
for (var i=optionLen; i<=size; i++) {
tmp.push(allOptions[i])
if (this.isAllSelected) {
this.values.push([this.type, allOptions[i].value])
}
}
element.children.push(...tmp)
}
})
//加载完新的数据之后,要让滚动条停留到上次滚动的位置
setTimeout(() => {
el.scrollTop = scrollTop
})
}
}
}
源码与使用方式
❝
源码 npm install cu-vue-cascader import CuVueCascader from 'cu-vue-cascader' vue.use(CuVueCascader) ❞// 几个重要的参数
allOptions: array 所有的餐素
selectAll: boolean 默认是否全选
allSelectedClass: {} 全选时候的样式
lazy: boolean 是否开启子选项的懒加载
loadSize: number 子选择每次加载的条数
评论