主要问题:使用该指令时,初次加载数据是会根据剩余空间来判断当前是否需滚动加载数据,但是在更新搜索数据后,就并不会根据剩余高度来加载数据,仅仅只是第一页
演示地址:element-playground平台
在上述的演示中,第一次进入是可以进行滚动加载,当点击重置按钮后,就无法进行滚动
问题分析:在element-plus的源码当中发现,当数据已经超出区域后,就销毁了区域没有填满的observer。点击重置后,updated时期只有当observer存在时才会检查区域是否填满
具体代码:
if (immediate) { // 通过MutationObserver监听元素变化 const observer = new MutationObserver( throttle(checkFull.bind(null, el, cb), CHECK_INTERVAL) ) el[SCOPE].observer = observer observer.observe(el, { childList: true, subtree: true }) checkFull(el, cb) } function checkFull(el: InfiniteScrollEl, cb: InfiniteScrollCallback) { const { containerEl, instance } = el[SCOPE] const { disabled } = getScrollOptions(el, instance) if (disabled || containerEl.clientHeight === 0) return if (containerEl.scrollHeight <= containerEl.clientHeight) { cb.call(instance) } else { destroyObserver(el) //销毁监听器 } } async updated(el) { if (!el[SCOPE]) { await nextTick() } else { const { containerEl, cb, observer } = el[SCOPE] // observer被销毁就不会执行下面的checkFull if (containerEl.clientHeight && observer) { checkFull(el, cb) } } },
解决方法:禁用infinite-scroll-immediate的属性,增加是否需要数据加载的判断逻辑
async function getTableData() { // 接口请求获取数据 const container = document.querySelector(`.${ns.b('content-table')}`) const content = document.querySelector(`.${ns.be('content-table', 'body')}`) if (container && content) { containerHeight.value = container.clientHeight contentHeight.value = content.scrollHeight // 检查是否需要继续加载 checkNeedMore() } } function checkNeedMore() { // 如果内容高度小于容器高度,且还有更多数据可以加载,则继续加载 if (contentHeight.value < (containerHeight.value - 60) && (!tableDataCount.value || tableData.value.length < tableDataCount.value)) scrollNextPage() }
contribution:既然是updated当中出现问题,就对源码进行修改。在updated当中根据是否设置了immediate,存在且当observer被销毁的时候就重新创建observer进行监听。
已提交贡献,待review
async updated(el) { if (!el[SCOPE]) { await nextTick() } else { const { containerEl, cb, instance } = el[SCOPE] const { immediate } = getScrollOptions(el, instance) if (containerEl.clientHeight && immediate) { if (!el[SCOPE].observer) { const observer = new MutationObserver( throttle(checkFull.bind(null, el, cb), CHECK_INTERVAL) ) el[SCOPE].observer = observer observer.observe(el, { childList: true, subtree: true }) } checkFull(el, cb) } } },