2017-09-22 1 views
0

Ich habe eine "Karte" -Komponente, die Daten für ein Objekt in einer festgelegten Weise darstellt.Wie erstellt man eine Liste/ein Gitter mit einer reaktionsfähigen Anzahl von Spalten, die reaktionsvirtualisiert sind?

Diese Kartenkomponenten haben eine vordefinierte Breite und Höhe.

Diese Kartenkomponenten werden in einer Liste dargestellt, und ich möchte, dass diese Liste den verfügbaren horizontalen Platz nutzt.

Ich möchte die Anzahl der Spalten als Reaktion ändern. z.B. Wenn die Elternkomponente für 3 Spalten zu eng wird, sollte sie auf 2 Spalten reduziert werden.

Konzeptionell ist dies ziemlich einfach zu erreichen. Die Größen der Komponenten sind gut bekannt, so dass keine Größenmessungen im laufenden Betrieb erforderlich sind. Es ist trivial, die Anzahl der Komponenten zu berechnen, die in die Breite der Liste passen, wodurch die Anzahl der Spalten angegeben wird.

Es gibt sogar die Option display:flex zu verwenden und die Berechnungen und das Layout für Sie durchführen zu lassen.

Ich versuche derzeit, react-virtualized zu verwenden, um diese reaktionsfähige Spaltenliste zu erreichen, da wir sie bereits in anderen Situationen in unserer App verwenden. Die Unterstützung der Virtualisierung ist auch ein starker Attraktor.

Die masonry Layout schien zu bieten, was wir wollen, aber ich "kann es nicht zum Laufen bringen".

Erfordert eine CellMeasurerCache, die entweder eine feste Breite oder eine feste Höhe benötigt. Das ist bedauerlich, da meine Komponenten sowohl eine feste Breite als auch eine feste Höhe haben, so dass die Messungen unnötig sind.

benutzte ich ein fixedWidth für die CellMeasurerCache als die cellPositioner eine columnWidth erfordert und ich nahm an, es wäre besser für sie das wird nicht denken ändern müssen.

Hier ist mein Code:

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} 
      /> 
     ); 
    } 
} 

Was ich fand, war, dass es die Karten machen tat, aber es gab nur eine einzige Säule, und das Mauerwerk Komponente height:auto; als Stil auf die Karte Komponentenelement angewandt! Das bedeutete, dass meine feste Höhe überschritten wurde, wodurch die Karten fehlformiert wurden.

Ich bin mir nicht sicher, warum es nur eine einzelne Spalte, und nicht zwei von ihnen rendert.

Das .ReactVirtualized__Masonry Element hat eine Höhe von 1000px, wie auf der Masonry Komponente festgelegt, aber es ist Kind, ReactVirtualized__Masonry__innerScrollContainer, eine Höhe von 335px; hat, und ich bin nicht sicher, warum, aber es ‚schneidet‘ die Karten, die kann gesehen werden.

HTML Screenshot

Bin ich etwas offensichtlich falsch mit Mauerwerk zu tun?

Ist Mauerwerk die falsche Wahl, und es gibt eine bessere Option innerhalb react-virtualized?

Ich versuche einen Hammer zu verwenden, um einen Nagel einzuschrauben, und sollte ich einfach etwas von Grund auf neu machen?

Antwort

1

Diese Kartenkomponenten haben eine vordefinierte Breite und Höhe.

Sind alle Karten die gleiche Breite und Höhe? In diesem Fall benötigen Sie die Komponente Masonry nicht. Es ist für Anwendungsfälle wie pinterest.com gedacht. (Ich habe es speziell für sie gebaut.)

Was Sie beschreiben, ist weniger komplex und kann daher effizienter durchgeführt werden. von List verwenden, um die Art von UI zu erstellen, die Sie beschrieben haben.

Wenn jede Karte eine andere Größe hat, ist Masonry die richtige zu verwendende Komponente.

Erfordert eine CellMeasurerCache, die entweder eine feste Breite oder eine feste Höhe benötigt. Das ist bedauerlich, da meine Komponenten sowohl eine feste Breite als auch eine feste Höhe haben, so dass die Messungen unnötig sind.

Leider ist dies der Fall. Ich baute die Masonry Komponente speziell für Pinterest's Use-Case und versuchte es zu optimieren, so viel wie ich könnte schnell anstatt generische.

+0

Vielen Dank für das Beispiel, ich habe das gut in meiner App jetzt funktioniert. – AndyJ

Verwandte Themen