2017-01-12 1 views
0

Я немного смущен, если я могу использовать компонент React Virtualized для решения моей проблемы. Я попытаюсь описать, что я делаю:React Virtualized: коллекция с ячейками с одинаковой фиксированной высотой, но различной шириной

Я использую React Virtualized на странице для отображения двух списков/коллекций элементов. Я закончил свою первую коллекцию, которая имеет элементы, которые имеют одинаковую ширину и высоту:

Collection where cells have same height & width

Первая коллекция была довольно прямо вперед и легко осуществить. Теперь я работаю над второй коллекцией, которая содержит изображения разных размеров. Я хочу, чтобы ячейки имели одинаковую высоту, но различную ширину (в зависимости от размеров изображения, конечно). Проблема заключается в том, что строки не всегда может иметь такое же количество клеток:

Collection where cells have same height but different width

возможно ли это достичь с React Виртуализованная? Если да, то как определить позицию в «cellSizeAndPositionGetter»?

+0

короткий nswer: вы не можете. Обходной путь, о котором я могу думать, - это расщепление всех ячеек в реальных строках, поэтому в строке 1 будут отображаться первые три изображения, а в строке 2 будут следующие четыре в вашем случае. Затем вы должны виртуализировать сами строки, а не отдельные ячейки. Это «по дизайну» ограничение виртуализированных списков вообще («список», а не «сетка»). –

+0

Я согласен с тем, что сказал Серджиу. Чтобы добавить немного больше - верхняя коллекция, которую вы показали, действительно должна быть «Grid», а не «Компонента». «Grid» более эффективен и проще в использовании. Второй, который вы показываете, может быть «List», но вычисление количества строк будет немного сложнее. – brianvaughn

+0

@brianvaughn Я предполагаю, что вы имеете в виду 'Collection', а не' Component'? В любом случае, я понимаю, о чем вы оба говорите. Думаю, я попробую «Сетка» для первой коллекции. Для второй коллекции я закончил использование [CassetteRocks/response-infin-scroller] (https://github.com/CassetteRocks/react-infinite-scroller). Когда у меня будет свободное время, я попробую снова реализовать вторую коллекцию, используя React Virtualized.Потому что мне очень нравится репо! :) Спасибо вам за ваш вклад. – Jooooooooohn

ответ

1

Недавно я использовал react-virtualizedList, чтобы отображать строки изображений с фиксированной высотой, карты с переменной шириной, и он отлично работал.

ListrowRenderer использует массив строк элементов карты изображений. То есть массив массивов реагирующих компонентов, как JSX.

См. Мою последнюю функцию, cardsRows, поскольку я строю строки на основе ширины элементов и ширины экрана.

Вот как это выглядит:

List rows layout

Надеется, что это помогает!

Некоторые фрагменты моего кода:

import {AutoSizer, List} from 'react-virtualized'; 

...

updateDimensions() { 
    this.setState({ 
     screenWidth: window.innerWidth, 
    }); 
} 

componentDidMount() { 
    window.addEventListener("resize", this.updateDimensions); 
} 


componentDidUpdate(prevProps, prevState) { 
    const props = this.props; 
    const state = this.state; 

    if (JSON.stringify(props.imageDocs) !== JSON.stringify(prevProps.imageDocs) || state.screenWidth !== prevState.screenWidth) 
     this.setState({ 
      cardsRows: cardsRows(props, state.screenWidth), 
     }); 
} 


rowRenderer({key, index, style, isScrolling}) { 
    if (!this.state.cardsRows.length) 
     return ''; 
    return (
     <div id={index} title={this.state.cardsRows[index].length} key={key} style={style}> 
      {this.state.cardsRows[index]} 
     </div> 
    ); 
} 

...

render() { 
    return (
      <div style={styles.subMain}> 
       <AutoSizer> 
        {({height, width}) => (<List height={height} 
               rowCount={this.state.cardsRows.length} 
               rowHeight={164} 
               rowRenderer={this.rowRenderer} 
               width={width} 
               overscanRowCount={2} 
         /> 
        )} 
       </AutoSizer> 
      </div> 
    ); 
} 

...

const cardsRows = (props, screenWidth) => { 

    const rows = []; 
    let rowCards = []; 
    let rowWidth = 0; 
    const distanceBetweenCards = 15; 

    for (const imageDoc of props.imageDocs) { 
     const imageWidth = getWidth(imageDoc); 

     if (rowWidth + distanceBetweenCards * 2 + imageWidth <= screenWidth) { 
      rowCards.push(cardElement(imageDoc)); 
      rowWidth += distanceBetweenCards + imageWidth; 
     } 
     else { 
      rows.push(rowCards); 
      rowCards = []; 
      rowWidth = distanceBetweenCards; 
     } 
    } 
    if (rowCards.length) { 
     rows.push(rowCards); 
    } 
    return rows; 
}; 


const styles = { 
    subMain: { 
     position: 'absolute', 
     display: 'block', 
     top: 0, 
     right: 0, 
     left: 0, 
     bottom: 0, 
    } 
}; 
Смежные вопросы