Element-plus 虚拟化列表 onEndReach 不触发回调的代餐方案

145 阅读6分钟

el-table-v2

周五的下午,我还在兢兢业业地写代码憧憬下班生活呢~! 发现el-table-v2的end-reach不触发回调方法(v2.9.5) #javsscript

<el-table-v2
      :columns="columns"
      :data="tableData"
      class="v-table"
      header-class="v-table-header"
      :estimated-row-height="120"
      :height="tableHeight"
      :width="1180"
      @end-reach="handleEndReach"
 />

issue github.com/element-plu… 里面有个issue说已经修复了 github.com/element-plu…

image.png

22年10月就merge了,可惜然并卵,我还是触发不了end-reach回调

算了,能不能用其他的方式来实现差不多的效果呢?

1.columns中有图片,每个图片可以用el-image的onLoad的回调来继续callback

只需要在onLoad的回调中,判断当前图片的索引与tableData的长度,是否满足一个范围,作为回调的判断条件。 但是,有个意想不到的点出现了,第一次渲染的时候不会把所有的el-image的onLoad触发一次,最后几张图片的首次加载没有触发回调,并且往上滚动也会触发onLoad回调,我的天老爷,这可是马上要下班了啊,我还有一堆接口文档没有对!急死了急死了 跟同事吐槽一下,要不用其他的组件库吧,直接进行一个烂的摆!naiveui好还是antd-vue好呢,纠结来,纠结去! 要不发会呆吧!嘿嘿嘿。

正当我盯着屏幕发呆的时候,突然发现el-table-v2还有一个事件回调rows-rendered

2.rows-rendered

解:

根据题意可知

  1. table-v2有一个已知属性 cache,代表为了更好的渲染效果预先多加载的行数
  2. table-v2的事件rows-rendered,回调函数中存在我需要的
type RowsRenderedParams = {
  rowsCacheStart: number
  rowsCacheEnd: number
  rowVisibleStart: number
  rowVisibleEnd: number
 }

通过解构出rowsCacheEndrowVisibleEnd,再加上当前tableData的长度,我们就可以判断出来是不是滚动到底部了,根据条件1,可使用了rowsCacheEnd,作为我的无限加载数据table的判断参数只要符合 rowsCacheEnd === tableData.value.length 就认为table滑动到了最底部~我真是个天才-v- 当然,作为一个勉强算老鸟的前端搬砖工人,肯定得注意一下接口请求的节流,加个isPending作为阀:

   const handleRowsRendered = ({rowsCacheEnd}) => {
     if (isPending.value) return
     if (rowsCacheEnd === tableData.value.length - 1) {
        getList()
     }
   }

效果就是还没有滑动到最底部,但是row加载完了,就会去请求接口,在这次请求返回之前,用isPending作为拦截,这样就不会出现多次调用,也不用担心竞态问题了。当然想要实现完全滑动到底部再请求或者做其他的事情,就使用 rowVisibleStart判断就好了。 激动的打工人,敏感的打工人,努力的打工人,在周五下午有感而码! 但是这些东西值钱嘛,在ai眼里是怎样的呢,我把上面的所有的信息都喂给deepseek,看它怎么思考的

嗯,我现在遇到了一个问题,el-table-v2的end-reach事件不触发回调。已经升级到v2.9.5了,但是还没解决。之前看到有个issue说已经修复了,不过显然问题依旧存在。我得想办法找到一个替代方案。先看看用户提到的两种可能的解决方案。

第一个方法是利用columns中的图片的onLoad事件。每个图片用el-image,然后在onLoad里判断当前图片的索引是否接近表格数据长度,从而触发加载更多。但用户发现第一次渲染时,最后几张图片的onLoad没有触发,而且上滑滚动时会触发,这样不可靠。尤其是临近下班,时间紧迫,这方法可能会有隐藏的问题,比如图片加载顺序或时机不确定,导致判断条件不准确。

第二个方法是使用rows-rendered事件。用户提供的思路是,利用rowsRenderedParams中的rowsCacheEnd,当其等于表格数据长度时触发加载。同时使用isPending来节流,防止重复请求。这个方法看起来更有希望,因为rows-rendered是在行渲染完成后触发,能够准确知道当前渲染的位置,比如缓存的行和可见行的范围。需要验证rowsCacheEnd是否确实在滚动到底部时会等于数据长度减一,并且确保这个条件只在真正触底时满足,避免误触发。

需要确认element-plus文档中rows-rendered的具体参数含义,rowsCacheEnd是否表示当前缓存渲染的最后一行索引,或者是否还有其他因素影响。例如,当数据长度为100,而rowsCacheEnd显示为99,可能就意味着触底了。这时候配合isPending标志,就可以避免多次请求。

但可能存在的情况是,rowsCacheEnd可能提前接近数据末尾,导致在真正滚动到底部前就触发请求。这时候需要判断合适的阈值。或者结合rowsVisibleEnd,因为rowVisibleEnd是用户实际可见的最后一行,当这个值达到数据末尾时再触发可能更准确。

用户提供的代码示例是将rowsCacheEnd与tableData的长度减一比较,但如果表格的数据是动态加载的,可能在初始加载时rowsCacheEnd的值会与数据长度不一致,需要确保在每次加载新数据后更新相关状态。

此外,需要考虑分页是否正确,比如每次加载的列表数据是否被正确追加到tableData中,并且表格组件能正确感知到数据变化,从而触发重新渲染。否则可能导致rowsCacheEnd无法正确更新到新的数据末尾。

可能还需要处理表格的高度和估计行高的设置是否正确,因为el-table-v2是虚拟滚动列表,需要正确的行高估算才能准确计算滚动位置。如果行高估算不准确,可能导致滚动事件触发过早或过晚,进而影响判断。

总结下来,采用rows-rendered事件结合rowsCacheEnd或rowVisibleEnd来判断滚动到底部,添加节流控制是一个可行的替代方案。需要确保:

  1. rowsCacheEnd的判断条件正确对应数据长度。
  2. 使用isPending来防止重复请求。
  3. 正确追加新数据到tableData中,并确保表格重新渲染。
  4. 行高估算准确,不影响虚拟滚动的计算。

最终代码需要测试在滚动到底部时rowsRendered事件中的参数是否正确,确保触发了加载更多的逻辑,同时没有误触发的情况。

好像没有什么卵用,我没解决之前,它也只会叫我再去看文档,再去注意版本,再问,再问,就开始出现幻觉,帮我乱改了。现在还想着给我多-1去让效果更流畅,只能说不知道插啥了,插一朵花吧。