< table />的无限滚动react.js中的元素 [英] Infinite Scrolling of <table /> element in react.js

查看:217
本文介绍了< table />的无限滚动react.js中的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

关于使用react.js的无限滚动,我有一个特别有趣的问题。

I have a particularly interesting problem with respect to infinite scrolling using react.js.

这里的目标是确保无论桌子有多大,我们只允许 render()返回所有行的固定子集。

The goal here is to make sure no matter how large a table becomes, we only ever let render() return a fixed subset of all rows.

我们将让 lowerVisualBound upperVisualBound 将行的子集表示为 render()到DOM上。

We will let lowerVisualBound and upperVisualBound denote the subset of rows to render() onto the DOM.

注意这些边界设置为大于视口,导致滚动条出现。

Note these bounds are set to be larger than the viewport, causing a scrollbar to appear.

当用户滚动时,我们将修改 lowerVisualBound upperVisualBound

We will modify lowerVisualBound and upperVisualBound as the user scrolls.

在这里,我们进一步表示

Here, we further denote


  • height 作为表格的可见部分的高度

  • totalHeight 作为整个表格的高度(包括 lowerVisualBound upperVisualBound

  • 之间的所有行scrollTop state.lastScrollTop 分别作为当前和上一个滚动顶部

  • height as the height of the visible portion of the table
  • totalHeight as the height of the entire table (that includes all rows between lowerVisualBound and upperVisualBound
  • scrollTop and state.lastScrollTop as the current and previous scroll top respectively

以下片段类型的伎俩 - 除了滚动条本身在加载其他数据后没有改变位置(即上限或下限 VisualBound重置)。这会导致用户的数据视图跳转。

The Following Snippet Kind of Does the Trick - Except the scrollbar itself does not change position after additional data has been loaded (i.e. upper or lower VisualBound reset). This causes the user's view of the data to jump.

    const rowDisplayBoundry = 2 * this.props.pageSize;
    if (scrollTop < this.state.lastScrollTop && scrollTop <= 0.0 * totalHeight) {
        // up scroll limit triggered
        newState.lowerVisualBound = Math.max(this.state.lowerVisualBound - this.props.pageSize, 0);
        newState.upperVisualBound = newState.lowerVisualBound + rowDisplayBoundry;
    } else if (scrollTop > this.state.lastScrollTop && (scrollTop + height) > totalHeight) {
        // down scroll limit triggered
        newState.upperVisualBound = this.state.upperVisualBound + this.props.pageSize;
        newState.lowerVisualBound = newState.upperVisualBound - rowDisplayBoundry;
    }
// TODO now what do we set scrollTop to, post these mutations? (presumably using a setTimeout())

任何人都可以建议算法来计算新的 scrollTop 这样更改视觉边界会保留用户的视图吗?

Can anyone suggest an algorithm to compute a new scrollTop such that changing the visual bound preserve the user's view?

注意我认为这应该是理论上的可能因为上面和下面之间的行数#下部视觉边界设置为>可以在视口中显示的内容。因此,在这些边界中的每个突变之后,用户不会丢失他在突变之前立即查看的任何行。这只是计算滚动条后突变的正确位置的问题。

Note I believe this should be theoretically possible because the # of rows between upper & lower visual bound is set to be > what can be displayed in the viewport. Therefore, after each mutation in those bounds, the user does not lose any rows that he was viewing immediately before the mutation. It is only a matter of computing the correct location the scrollbar post-mutation.

推荐答案

以下似乎有效...虽然不确定是否存在不存在的极端情况(请原谅相当自由地使用jQuery选择器进行此演示)

The following appears to have worked ... though not sure if there are corner cases where it doesn't (please excuse the rather liberal use of jQuery selector for this demostration)

handleScroll: function (e) {
    const $target = $(e.target);
    const scrollTop = $target.scrollTop();
    const height = $target.height();
    const totalHeight = $target.find("tbody").height();
    const avgRowHeight = totalHeight / (this.state.upperVisualBound - this.state.lowerVisualBound);
    /**
     * always update lastScrollTop on scroll event - it helps us determine
     * whether the next scroll event is up or down
     */
    var newState = {lastScrollTop: scrollTop};

    /**
     * we determine the correct display boundaries by keeping the distance between lower and upper visual bound
     * to some constant multiple of pageSize
     */
    const rowDisplayBoundry = 2 * this.props.pageSize;
    if (scrollTop < this.state.lastScrollTop && scrollTop <= 0) {
        // up scroll limit triggered
        newState.lowerVisualBound = Math.max(this.state.lowerVisualBound - this.props.pageSize, 0);
        newState.upperVisualBound = newState.lowerVisualBound + rowDisplayBoundry;
        // if top most rows reached, do nothing, otherwise reset scrollTop to preserve current view
        if (!(newState.lowerVisualBound === 0))
            setTimeout(function () {
                $target.scrollTop(Math.max(scrollTop + this.props.pageSize * avgRowHeight, 0));
            }.bind(this));

    } else if (scrollTop > this.state.lastScrollTop && (scrollTop + height) >= totalHeight) {
        // down scroll limit triggered
        newState.upperVisualBound = this.state.upperVisualBound + this.props.pageSize;
        newState.lowerVisualBound = newState.upperVisualBound - rowDisplayBoundry;
        setTimeout(function () {
            // TODO ensure that new scrollTop doesn't trigger another load event
            // TODO ensure this computationally NOT through flagging variables
            $target.scrollTop(scrollTop - this.props.pageSize * avgRowHeight);
        }.bind(this));
    }
    this.setState(newState);
}

这篇关于&lt; table /&gt;的无限滚动react.js中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆