【问题标题】:How to make a list/grid with a responsive number of columns using react-virtualized?如何使用反应虚拟化制作具有响应数量列的列表/网格?
【发布时间】:2018-03-04 05:52:43
【问题描述】:

我有一个“卡片”组件,它以固定的方式呈现对象的数据。

这些卡片组件具有预定义的宽度和高度。

这些卡片组件将显示在一个列表中,我希望该列表能够利用可用的水平空间。

我希望列数能够相应地改变。例如如果父组件对于 3 列变得太窄,那么它应该下降到使用 2 列。

从概念上讲,这很容易实现。组件大小是众所周知的,因此无需即时测量大小,计算可以容纳在列表宽度中的组件数量(即列数)很简单。

甚至可以选择使用 display:flex 并让它为您进行计算和布局。

我目前正在尝试使用react-virtualized 来实现这个响应列列表,因为我们已经在我们的应用程序的其他情况下使用它。它对虚拟化的支持也是一个强大的吸引力。

masonry 布局似乎提供了我们想要的,但我“无法让它工作”。

它需要CellMeasurerCache,它需要固定宽度或固定高度。这是不幸的,因为我的组件具有固定的宽度和高度,因此没有必要进行测量。

我将fixedWidth 用于CellMeasurerCache,因为cellPositioner 需要columnWidth,我认为它认为不需要更改会更好。

这是我的代码:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { RouteComponentProps } from 'react-router-dom';
import { AutoSizer, Masonry, WindowScroller, CellMeasurer, CellMeasurerCache, MasonryCellProps, createMasonryCellPositioner } from 'react-virtualized';
import { Task } from '../../store/tasks';
import { TaskCard } from './taskcard';

type TaskCardListProps = {
    scrollElement?: any;
    tasks: Task[];
};

type TaskCardListState = {};

export class TaskCardList extends React.Component<TaskCardListProps, TaskCardListState> {
    public render() {
        const { tasks, scrollElement } = this.props;

        const cache = new CellMeasurerCache({            
            defaultHeight: 120,
            defaultWidth: 400,
            fixedWidth: true
        });

        const cellPositioner = createMasonryCellPositioner({
            cellMeasurerCache: cache,
            columnCount: 2,
            columnWidth: 400,
            spacer: 10
        });

        const cellRenderer = (props: MasonryCellProps) => {
            const { index, key, parent, style } = props;
            const task = tasks[index];

            return (
                <CellMeasurer cache={cache} index={index} key={key} parent={parent}>
                    <TaskCard { ...task } />
                </CellMeasurer>
            )
        };

        return (
            <Masonry
                autoHeight={false}
                cellCount={tasks.length}
                cellMeasurerCache={cache}
                cellPositioner={cellPositioner}
                cellRenderer={cellRenderer}
                height={1000}
                width={1500}
            />
        );
    }
}

我发现它确实渲染了卡片,但只有一个列,并且 masonry 组件将 height:auto; 作为样式应用于卡片组件元素!这意味着它超出了我的固定高度,导致卡片变形。

我不确定为什么它只呈现一列,而不是其中的两列。

.ReactVirtualized__Masonry 元素的高度为 1000 像素,正如在 Masonry 组件上设置的那样,但它是子元素 ReactVirtualized__Masonry__innerScrollContainer,高度为 335px;,我不知道为什么,但它是“切断”可见的卡片。

我是不是在做 Masonry 明显错误的事情?

Masonry 是错误的选择吗,react-virtualized 有更好的选择吗?

我是不是想用锤子拧钉子,我应该从头开始做点什么吗?

【问题讨论】:

    标签: typescript react-virtualized


    【解决方案1】:

    这些卡片组件具有预定义的宽度和高度。

    所有卡片的宽度和高度都相同吗?如果是这样,您不需要 Masonry 组件。它适用于 pinterest.com 等用例。 (实际上我是专门为他们打造的。)

    您所描述的内容不那么复杂,因此可以以更有效的方式完成。 Here's an example 使用 List 构建您描述的那种 UI。

    如果每张卡片的尺寸不同,那么Masonry 是要使用的正确组件。

    它需要一个CellMeasurerCache,它需要一个固定的宽度或一个固定的高度。这是不幸的,因为我的组件具有固定的宽度和高度,因此没有必要进行测量。

    不幸的是,这是真的。我专门为 Pinterest 的用例构建了 Masonry 组件,并尝试尽可能地优化它,使其 fast 而不是 generic

    【讨论】:

    • 非常感谢您提供的示例,我的应用程序现在运行良好。
    • 4 年后也帮助了我。谢谢@bvaughn!
    猜你喜欢
    • 2022-01-10
    • 2017-08-20
    • 1970-01-01
    • 2017-01-28
    • 2018-10-16
    • 2017-07-13
    • 2017-05-18
    • 2021-10-09
    • 2021-05-25
    相关资源
    最近更新 更多