简体   繁体   English

滚动时,React虚拟化列表是否有可能捕捉到整行?

[英]Is it possible for a React Virtualized list to snap to a full row when scrolling?

I have a React Virtualized <List> component that's used as a drop-down menu. 我有一个React Virtualized <List>组件,它用作下拉菜单。 I'd like the list to scroll a whole row at a time, like a normal OS-level menu, or at least snap to a whole row when the scrolling stops. 我希望列表一次滚动一整行,就像普通的OS级菜单一样,或者至少在滚动停止时捕捉到整行。

I've set scrollToAlignment="top" , thinking that might do it, but now I realized that messed up the scrolling behavior when setting scrollToIndex . 我已经设置了scrollToAlignment="top" ,以为可能做到这一点,但是现在我意识到,在设置scrollToIndex时弄乱了滚动行为。

There's an onScroll event, and I suppose I could set a timeout to fire if another event wasn't received within a certain window, and then force the scrollTop to show a full row. 有一个onScroll事件,我想如果可以在某个窗口中未收到另一个事件的情况下将超时设置为触发,然后强制scrollTop显示完整行。 But I was hoping there might be a cleaner way to do it. 但是我希望可以有一种更清洁的方法来做到这一点。

Possible solution 可能的解决方案

Similar to brianvaughn's answer below , I put together a solution using the onScroll event to call a debounced function that snaps the scrollTop to a whole row increment after a short delay: 下面的 brianvaughn的答案类似,我使用onScroll事件组合了一个解决方案,以调用一个去抖动的函数,该函数在短暂的延迟后将scrollTop捕捉到整个行的增量:

const RowHeight = 45;

const ResultsList = React.createClass({
    list: null,

    snapRows: _.debounce(function(scrollTop)
    {
        this.list.scrollToPosition(Math.round(scrollTop / RowHeight) * RowHeight);
    }, 100),

    handleRef: function(ref)
    {
        this.list = ref;
    },

    onScroll: function(event)
    {
        this.snapRows(event.scrollTop);
    },

    rowRenderer: function(data)
    { ... },

    render: function()
    {
        var props = this.props;

        return <List
            ref={this.handleRef}
            width={490}
            height={450}
            rowCount={props.items.length}
            rowHeight={RowHeight}
            rowRenderer={this.rowRenderer}
            scrollToIndex={props.selectedIndex}
            onScroll={this.onScroll}
            {...props}
        />
    }
});

But I'm not really happy with it. 但是我对此并不满意。 The snap at the end of the scroll is a bit distracting, and can feel a little weird if you're still holding on to the scrollbar thumb. 滚动末尾的捕捉有些分散注意力,如果您仍然按住滚动条拇指,可能会感到有些奇怪。

I think the only way to make it feel like you're updating a list of items rather than smoothly scrolling a page is to handle the scroll events and manually position the elements so the rows are always snapped to an even row increment. 我认为,使您感觉像是在更新项目列表而不是平滑滚动页面的唯一方法是处理滚动事件并手动定位元素,以便行始终按均匀的行增量对齐。 I built a virtual list like that back in the days of IE5, but was hoping for a more modern implementation. 早在IE5的时候,我就建立了一个类似的虚拟列表,但是希望有一个更现代的实现。 :) :)

This is not a use-case I've implemented before so I haven't given it much thought, but you could use a debounced onScroll or onSectionRendered handler to call scrollToCell and snap to a specific row. 这不是我之前实现的用例,因此我没有考虑太多,但是您可以使用去抖动的onScrollonSectionRendered处理函数来调用scrollToCell并捕捉到特定行。

Edit : Here's a rough example of what I'm talking about: https://codesandbox.io/s/545y634jxx 编辑 :这是我正在谈论的一个粗略示例: https : //codesandbox.io/s/545y634jxx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM