这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战
写在前面
这是之前开发中遇到的问题,筛选选项中有一栏为选择标签。标签数据是一次性返回的,标签数据本身只有两级:一级标签分类,二级标签数据。二级标签数据会出现返回几千条的情况。单独多选几个标签本身不会有太大问题,但出现选中某个标签分类时,页面会有明显卡顿。
分析
减少页面中实际渲染的标签数
默认每个二级标签数据只加载前200个。
页面初始化绑定滚动事件,向上滚动距离 + 展示框高度 > 选项实际高度时即滚动到底。此时需要在该标签分类下判断数据是否加载完毕,若没有全部加载完则 option 拼接下页数据 200 或剩余数据,并在数据在页面渲染完成后滚动到对应位置 dom.scrollTo(0, scrollTop)。
const Cascader_DOM_warp = Cascader_DOM.getElementsByClassName('el-cascader-menu__wrap')[0]
// 绑定滚动事件;
Cascader_DOM_warp.addEventListener('scroll', function (event) {
let e = event.target;
if (e.scrollTop + Math.ceil(e.getBoundingClientRect().height) >= e.offsetHeight) {
// 节流;
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
_this.loadMore(Cascader_DOM_warp, e.scrollTop)
}, 50)
}
})
搜索时拼接标签数据
实际用户使用过程中会用到模糊搜索。若不做后续处理,当前标签未渲染出来的选项是搜索不出来的。
在默认筛选钩子调用前 before-filter:备份当前标签数据。调用后台并把对应每组下的标签查询结果拼入。注意返回为 Promise, resolve(options拼接结果)。
用户选完后关闭若把标签数据还原,不在该标签内的数据会自动被清空。
beforeFilterEnterpriseLabel(name) {
this.companyTags
let params = {
name
}
return new Promise((resolve, reject) => {
http
.searchCompanyTag(params)
.then((res) => {
this.lastCompanyTags = JSON.parse(JSON.stringify(this.companyTags))
let filterArr = []
res.data.forEach((item) => {
item.label = item.group_name
item.value = item.group_name
item.group_list.forEach((tagItem) => {
tagItem.label = tagItem.label_name
tagItem.value = tagItem.id
})
item.children = item.group_list
// 新查出来在哪个标签组
// 标签组下children合并
let i = this.casLevel0KeyArr.indexOf(item.value)
item.children.forEach((searchItem) => {
if (
JSON.stringify(this.companyTags[i].children).includes(
`${searchItem.label}`
)
) {
} else {
let arr = [...this.companyTags[i].children, searchItem]
this.companyTags[i].children = arr
}
})
})
resolve(this.companyTags)
})
.catch(() => {})
})
}
还存在的问题:一是标签渲染一直滚动还是会出现过多的问题。二是若用户搜索选择后再次进入并滚动触发加载,可能会出现同一个选项 value, tag 出现两次的情况。
遗留问题后续看看怎么解决吧。。。欢迎大家给我点提示和思路。😢