Diese Komponente unterstützt eine vertikale Liste von Elementen innerhalb eines scrollbaren Bereichs. Der sichtbare Teil der Liste wird als "Viewport" bezeichnet. Die Liste ist virtualisiert, was bedeutet, dass Elemente nur gerendert werden, wenn sie sich im Viewport befinden (oder knapp darüber oder darunter).
Im Gegensatz zu anderen Listenansichten (wie der in React Native bereitgestellten ListView) unterstützt diese Komponente Listen mit heterogenen Elementen unterschiedlicher Höhen und völlig unterschiedlicher Typen.
Jedes Element in der Liste wird durch ein VirtualListViewItemInfo-Objekt beschrieben. Die Liste der Elemente wird durch eine geordnete Liste, die an die itemList-Eigenschaft übergeben wird, spezifiziert. Wenn ein Element in Sicht kommt, wird es mithilfe des renderItem-Callbacks gerendert. Zusätzliche Felder können vom Aufrufer nach Belieben zum VirtualListViewItemInfo hinzugefügt werden. Es ist zum Beispiel manchmal nützlich, zusätzliche identifizierende Informationen wie einen Elementtyp oder eine element-spezifische Render-Methode einzufügen.
Für jedes Element muss eine Höhe angegeben werden. Standardmäßig wird angenommen, dass diese Höhe korrekt und konstant ist. Wenn Sie die Höhe des Objekts nicht kennen oder sie sich ändern kann, kann die Höhe zur Laufzeit gemessen werden. Diese Option ist teuer, daher sollte sie möglichst vermieden werden.
Optional unterstützt es Animationen von Elementen, wenn diese in der Liste hinzugefügt, entfernt oder verschoben werden.
Wenn Elemente vor oder hinter dem sichtbaren Bereich hinzugefügt werden, versucht es, die aktuelle Position der sichtbaren Elemente beizubehalten und passt die Scrollposition und die Listenhöhe entsprechend an.
Zur Installation: npm install reactxp-virtuallistview
Die VirtualListView verwendet eine Reihe von Tricks, um die Leistung zu verbessern.
Sie verwendet eine Technik namens "Cell Recycling" (Zellrecycling), um die Anzahl der Mounts und Unmounts zu minimieren. Eine Zelle ist ein Container für ein Listenelement. Wenn eine Zelle nicht mehr sichtbar ist, kann sie vorübergehend ausgeblendet und dann für das nächste Element, das sichtbar wird, wiederverwendet werden. Diese Optimierung ist am effektivsten, wenn die recycelte Zelle und ihr Inhalt für ein Element mit ähnlichem Inhalt verwendet werden. Aus diesem Grund müssen Aufrufer ein "template"-Feld angeben, um ähnliche Elemente zu identifizieren. In einigen Fällen kann das Deaktivieren des Zellrecyclings von Vorteil sein, da recycelte Zellen ihren normalen React-Lebenszyklus auch dann fortsetzen, wenn sie nicht sichtbar sind, was in einigen Fällen zu übermäßigen Hintergrund-Neu-Renderings führen kann. Bei der Kombination von VLV mit React-Bibliotheken (wie ReSub), deren Abonnements von Komponenten verwaltet werden, kann dieses Verhalten auftreten. Um das Zellrecycling für bestimmte Zellen zu deaktivieren, schließen Sie das Template-Feld aus dem Elementdeskriptor aus.
Sie unterstützt auch "Overdraw" (Überzeichnung), um Elemente oberhalb und unterhalb des Viewports zu rendern. Dies minimiert die Wahrscheinlichkeit, dass der Benutzer zu einem neuen Teil der Liste scrollt, bevor neue Elemente in diesem Bereich gerendert werden können. Overdraw wird erst verwendet, nachdem der Viewport initial gefüllt ist. Dies reduziert die Leistungsauswirkungen des Renderns.
Sie begrenzt auch die Anzahl der Elemente, die sie jedes Mal rendert, um eine übermäßige Auslastung des JavaScript-Threads zu vermeiden.
Sie unterstützt einen Spezialmodus, in dem Elemente nur neu gerendert werden, wenn sich das entsprechende VirtualListViewItemInfo ändert. Dieser Modus erfordert, dass die renderItem-Methode nur Informationen aus diesem Objekt verwendet. Um diesen Modus zu nutzen, setzen Sie die prop skipRenderIfItemUnchanged auf true.
import { VirtualListView, VirtualListViewItemInfo }
from 'reactxp-virtuallistview';
// Extend VirtualListViewItemInfo to include display text
interface FruitListItemInfo extends VirtualListViewItemInfo {
text: string;
}
interface FruitListState {
items: FruitListItemInfo[];
}
const _headerItemHeight = 20;
const _fruitItemHeight = 32;
const _headerItemTemplate = 'header';
const _fruitItemTemplate = 'fruit';
class FruitListView extends RX.Component<null, FruitListState> {
constructor() {
super();
this.state = {
items: [{
key: 'header1',
height: _headerItemHeight,
text: 'Domstic Fruits',
template: _headerItemTemplate
}, {
key: 'bannana',
height: _fruitItemHeight,
text: 'Banana',
template: _fruitItemTemplate
}, {
key: 'apple',
height: _fruitItemHeight,
text: 'Apple',
template: _fruitItemTemplate
}]
};
}
render() {
return (
<VirtualListView
itemList={ this.state.items }
renderItem={ this._renderItem }
animateChanges={ true }
skipRenderIfItemUnchanged={ true }
/>
);
}
private _renderItem(details: VirtualListViewCellRenderDetails<FruitListItemInfo>) {
const viewStyle = RX.Styles.createViewStyle({
height: details.item.height,
backgroundColor: item.template === _headerItemTemplate ?
'#ddd' : '#fff',
alignItems: 'center'
}, false);
return (
<RX.View style={ viewStyle }>
<RX.Text>
{ details.item.text }
</RX.Text>
</RX.View>
);
}
}
interface VirtualListViewItemInfo {
// A string that uniquely identifies this item.
key: string;
// Specifies the known height of the item or a best guess if the
// height isn't known.
height: number;
// Specifies that the height is not known and needs to be measured
// dynamically. This has a big perf overhead because it requires a
// double layout (once offscreen to measure the item). It also
// disables cell recycling. Wherever possible, it should be avoided,
// especially for perf-critical views.
measureHeight?: boolean;
// Specify the same "template" string for items that are rendered
// with identical or similar view hierarchies. When a template is
// specified, the list view attempts to recycle cells whose templates
// match. When an item scrolls off the screen and others appear on
// screen, the contents of the cell are simply updated rather than
// torn down and rebuilt.
template: string;
// Is the item navigable by keyboard or through accessibility
// mechanisms?
isNavigable?: boolean;
}
// Should the list animate additions, removals and moves within the list?
animateChanges?: boolean;
initialSelectedKey?: string;
// Ordered list of descriptors for items to display in the list.
itemList: VirtualListViewItemInfo[];
// Use this if you want to vertically offset the focused item from the
// top of the viewport when using keyboard nav
keyboardFocusScrollOffset?: number;
// Logging callback to debug issues related to the VirtualListView.
logInfo?: (textToLog: string) => void;
// Callback when an item in the VLV is selected
onItemSelected?: (item: ItemInfo) => void;
// Optional padding around the scrolling content within the list.
padding?: number;
// Callback for rendering item when it becomes visible within view port.
renderItem: (renderDetails: VirtualListCellRenderDetails<ItemInfo>) =>
JSX.Element | JSX.Element[];
// If true, allows each item to overflow its visible cell boundaries;
// by default, item contents are clipped to cell boundaries.
showOverflow?: boolean;
// By default, VirtualListView re-renders every item during the render.
// Setting this flag to true allows the list view to re-render only
// items from itemList whose descriptor has changed, thus avoiding
// unnecessary rendering. It uses _.isEqual to perform this check. In
// this mode, renderItem should not depend on any external state, only
// on VirtualListViewItemInfo, to render item.
skipRenderIfItemUnchanged?: boolean;
// ID that can be used to identify the instantiated element for testing purposes.
testId: string = undefined;
// Pass-through properties for scroll view.
keyboardDismissMode?: 'none' | 'interactive' | 'on-drag';
keyboardShouldPersistTaps?: boolean;
disableScrolling?: boolean;
scrollsToTop?: boolean; // iOS only, scroll to top when user taps on status bar
disableBouncing?: boolean; // iOS only, bounce override
scrollIndicatorInsets?: { top: number, left: number,
bottom: number, right: number }; // iOS only
onLayout?: (e: RX.Types.ViewOnLayoutEvent) => void;
scrollEventThrottle?: number;
onScroll?: (scrollTop: number, scrollLeft: number) => void;
scrollXAnimatedValue?: RX.Types.AnimatedValue;
scrollYAnimatedValue?: RX.Types.AnimatedValue;
// Scrolls the view to the specified top value (specified in pixels).
scrollToTop(animated = true, top = 0);
// Sets selection & focus to specified key
selectItemKey(key: string);