#react-virtualized
#реагировать виртуализировано
Вопрос:
Я настраивал компонент VirtualScroll (список) почти целый день, но безуспешно.
Я создаю веб-приложение для общения в чате, в котором для отображения сообщений в чате используется список виртуализированных реакций. Поскольку сообщение может иметь разное содержимое и разную высоту, я использую react-measure для вычисления высоты элемента и выдачи recomputeRowHeights в rowRenderer .
Результат плохой, список VirtuallScroll будет прыгать всякий раз, когда я останавливал прокрутку. Например, когда я прокручиваю половину браузера, я должен видеть середину сообщений, но это всегда внезапно смещает смещение. Пожалуйста, взгляните на записанное видео: https://drive.google.com/file/d/0B_W64UoqloIkcm9oQ08xS09Zc1k/view?usp=sharing
Поскольку я использую только компонент списка и автоопределения, я только адаптирую требуемый файл css в свой проект, который выглядит как «
.VirtualScroll {
width: 100%;
outline: none;
}
«`
Для метода рендеринга я вложил много гибких компонентов внутри rowRender: вот код:
«`
render() {
const inChat = this.context.store.getState().inChat;
const {conversationList} = this.state;
const imgUrl = 'img/builtin-wallpaper-1.jpg';
const backgroundStyle = {
backgroundImage: 'url(' imgUrl ')',
backgroundRepeat: 'no-repeat',
backgroundSize: 'cover',
backgroundPosition: 'top left'
};
if (inChat.id === this.id amp;amp; inChat.status === 'FETCHING'){
return (
<Box column center height="80%">
<CircularProgress />
</Box>
);
} else if (inChat.id === this.id amp;amp; inChat.status === 'FETCHED'){
return (
<Box column flex="1 0 100%" style={backgroundStyle}>
<HorizontalToolBar/>
<AutoSizer disableHeight={true}>
{({ width }) => (
<List
ref={(element) => {this.VirtualScroll = element;}}
className='VirtualScroll'
height={window.innerHeight - toolbarHeight - textAreaHeight}
overscanRowCount={10}
noRowsRenderer={this._noRowsRenderer.bind(this)}
rowCount={conversationList.length}
rowHeight={i => {
return (Measured_Heights[i.index] | 20); // default Height = 58
}}
rowRenderer={this._rowRenderer}
scrollToIndex={undefined} // scroll to latest item
width={width}
/>
)}
</AutoSizer>
<InputControl chatId={this.id} sendChatText={this._sendChatText.bind(this)}/>
</Box>
);
} else {
return null;
}
}
_rowRenderer ({ index, key, style, isScrolling }) {
console.log(Measured_Heights);
const rowData = this._getDatum(index);
// let renderItem;
// console.log('index = ' index ' key = ' key);
if (rowData.type == 'conversation') {
if (rowData.data.type == netModule.TYPE_SYSTEM) {
// system message
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<SystemMessage data={rowData.data}/>
</Measure>
)
}
if (rowData.data.senderId == this.state.selfProfile.username) {
// outgoing message
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<RightMessage
screenWidth={(window.innerWidth - leftToolBarWidth) / 2 }
screenHeight={window.innerHeight - toolbarHeight}
data={rowData.data}/>
</Measure>
);
} else {
// incoming message
// append userProfile to left messages
return (
<Measure key={key} onMeasure={(dims) => this._onMeasure(index, dims)}>
<LeftMessage
userId={rowData.data.senderId}
userProfile={this.state.groupUserProfiles[rowData.data.senderId]}
screenWidth={(window.innerWidth - leftToolBarWidth) / 2 }
screenHeight={window.innerHeight - toolbarHeight}
data={rowData.data}/>
</Measure>
);
}
}
}
«`
Я прочитал пару документов о том, что Flexbox может перехватывать событие прокрутки, но, несмотря на то, что я добавил overflow-y: hidden во вложенный компонент, я не видел, чтобы проблема исчезла. Вы когда-нибудь видели это неправильное поведение прокрутки с компонентом списка раньше?
Любое предложение приветствуется.
Ответ №1:
Я не вижу видео, но я думаю, что у меня было что-то подобное в последнее время. Из того, что я вижу, вы не используете style
параметр, переданный в ваш _rowRenderer
метод. Этот параметр содержит некоторые преобразования CSS, которые заставляют строку отображаться в правильном вертикальном положении в списке прокрутки.