业务场景:一级二级数据量不多 ,一次返回,第三级数据点击二级时请求 ,第一级选项不可选,第三级选项加载出来的情况下第二级选项才能全选
问题:实现过程中发现三级数据量过多(8千多条)会造成浏览器卡死
解决:三级选项分页显示
欢迎各位小伙伴评论区多多指教 (有时间会优化,整理demo出来)
主要代码
html
<el-cascader v-model="tagsFocus" :options="options" :props="propsTag" filterable collapse-tags placeholder="请选择" @expand-change="nodeChange" @change="blurData" />
js
1.在nodeChange中判断是否是第二级选项 去请求数据
2.getLevel3Data请求处理数据
3.监听滚动事件 scrollCallback
nodeChange(val) {
// cascaderScroll 用来记录滚动数据 page:第几页 data要滚动的三级选项全部数据
this.cascaderScroll.page = null
this.cascaderScroll.data = []
// 解除绑定的滚动事件
if (this.currentScroll) {
this.currentScroll.removeEventListener('scroll', this.eventListenerScroll(this.currentScroll))
}
// 判断点击的是第二级选项 请求数据
if (val.length === 2) {
this.getLevel3Data(val[1])
}
},
async getLevel3Data(obj, node) {
const data = {
topics: obj.topics,
tagType: obj.name
}
try {
// node.loading = true
const res = await searchTag(data)
let addData = res.data
this.cascaderScroll.isScroll = false
this.cascaderScroll.tagName = obj.name
this.cascaderScroll.pName = obj.topics
//如果数据超过2000条才开始分页
if (addData.length > 2000) {
this.cascaderScroll.isScroll = true
this.cascaderScroll.data = [...addData]
this.cascaderScroll.page = {
total: this.cascaderScroll.data.length,
totalPage: Math.ceil(this.cascaderScroll.data.length / 10),
size: 10,//一页10条数据
index: 0
}
addData = addData.slice(0, 10)
}
// 将数据添加到options
this.addOptionData(addData)
const _this = this
//
if (this.cascaderScroll.isScroll) { // 滚动的 要禁止全选
setTimeout(() => {
document.querySelectorAll('.tags .el-scrollbar:nth-child(2) .el-checkbox').forEach(el => {
var span = el.nextSibling
if (span.innerText === obj.name) {
var input = el.querySelectorAll('input')
console.log(span.innerText + '-----------------' + obj.name, input[0])
input[0].setAttribute('disabled', true)
el.onclick = () => {
_this.$message.info('当前标签不可全选!')
}
}
})
}, 500)
// 监听滚动事件
setTimeout(() => {
this.scrollCallback()
}, 1000)
}
} catch (e) {
console.info(e)
}
},
scrollCallback() { // 不超过2000条数据不监听 不分页 if (!this.cascaderScroll.isScroll) { return } const panel = document.querySelectorAll('.tags .el-scrollbar:nth-child(3) .el-cascader-menu__wrap.el-scrollbar__wrap') const length = panel.length this.currentScroll = panel[length - 1] if (this.currentScroll) { this.currentScroll.addEventListener('scroll', this.eventListenerScroll(this.currentScroll)) } }, eventListenerScroll(el) { return () => { // console.log('===========eventListenerScroll===================') if (!this.cascaderScroll.page || !this.cascaderScroll.page.totalPage) { // 如果没有分页信息返回 return } const scrollTop = el.scrollTop const clientHeight = el.clientHeight const scrollHeight = el.scrollHeight // 滚动条滚动的距离 const scrollStep = scrollTop - this.scrollValue // 更新——滚动前,滚动条距文档顶部的距离 this.scrollValue = scrollTop let direction = 'down' if (scrollStep < 0) { if (scrollStep <= -160) { direction = 'down' } else { direction = 'up' } } else { direction = 'down' } console.log(scrollTop + '-------------------------------' + direction) // 滚动条到达了底部 let scroll = false if (scrollTop + clientHeight === scrollHeight) { if (this.cascaderScroll.page.totalPage > this.cascaderScroll.page.index) { console.log('下一页') ++this.cascaderScroll.page.index scroll = true } } else if (scrollTop <= 5 && direction === 'up') { // console.log('向上滚动') if (this.cascaderScroll.page.index > 1) { console.log('上一页') --this.cascaderScroll.page.index scroll = true } } // 需要重新加载数据 if (scroll) { console.log('当前页:' + this.cascaderScroll.page.index) const start = (this.cascaderScroll.page.index) * 10 let end = (this.cascaderScroll.page.index + 1) * 10 if (end > this.cascaderScroll.page.total) { end = this.cascaderScroll.page.total } // console.log('当前页数据===================' + start, end) // console.log(this.cascaderScroll.data.slice(start, end)) this.addOptionData(this.cascaderScroll.data.slice(start, end)) // 加载完新的数据之后,要让滚动条停留到上次滚动的位置 避免滚动过快 加载数据错误 setTimeout(() => { if (direction === 'up') { el.scrollTop = 160 } else { el.scrollTop = 8 } }) } } },
// 添加数据到options addOptionData(data) { const { pName, tagName } = this.cascaderScroll this.options.forEach(tag1 => { if (tag1.label === pName) { tag1.children.forEach(tags2 => { if (tags2.label === tagName) { tags2.children = data } }) } }) },