react-virtualized 를 사용 하여 그림 동적 높이 의 긴 목록 을 실현 하 는 문제

가상 목록 은 스크롤 용기 요소 의 시각 영역 에 따라 긴 목록 데이터 의 일부 데 이 터 를 렌 더 링 하 는 기술 입 니 다.가상 목록 은 긴 목록 장면 에 대해 흔히 볼 수 있 는 최적화 이다.목록 에 백 개의 키 요 소 를 과장 하 는 사람 이 별로 없 기 때문에 스크롤 바 가 가로 또는 세로 로 굴 러 갈 때 시각 영역 안의 요 소 를 렌 더 링 하면 된다.
개발 중 에 닥 친 문제
1.긴 목록 에 있 는 그림 은 원래 그림 과 같은 비율 을 유지 해 야 합 니 다.세로 로 구 르 는 것 은 너비 가 변 하지 않 는 상황 에서 모든 그림 의 높이 는 동적 입 니 다.이 목록 항목 의 높이 가 변화 하면 이 목록 항목 과 그 후의 모든 목록 항목 의 위치 정보 에 영향 을 줄 수 있 습 니 다.
2.그림 width,height 는 그림 불 러 오기 가 완료 되 어야 얻 을 수 있 습 니 다.
해결 방안
저 희 는 react-virtualized 의 list 구성 요 소 를 사용 합 니 다.공식 적 으로 제 시 된 예 입 니 다.

import React from 'react';
import ReactDOM from 'react-dom';
import {List} from 'react-virtualized';

// List data as an array of strings
const list = [
  'Brian Vaughn',
  // And so on...
];

function rowRenderer({
  key, // Unique key within array of rows
  index, // Index of row within collection
  isScrolling, // The List is currently being scrolled
  isVisible, // This row is visible within the List (eg it is not an overscanned row)
  style, // Style object to be applied to row (to position it)
}) {
  return (
    <div key={key} style={style}>
      {list[index]}
    </div>
  );
}

// Render your list
ReactDOM.render(
  <List
    width={300}
    height={300}
    rowCount={list.length}
    rowHeight={20}
    rowRenderer={rowRenderer}
  />,
  document.getElementById('example'),
);

그 중에서 rowHeight 는 각 줄 의 높이 로 고정 높이 로 들 어 갈 수도 있 고 function 으로 들 어 갈 수도 있다.하위 요소 의 높이 가 바 뀔 때마다 recopuuteRow Heights 방법 을 호출 하고 색인 을 지정 한 후 줄 의 높이 와 오프셋 을 다시 계산 해 야 합 니 다.
구체 적 실현

const ImgHeightComponent = ({ imgUrl, onHeightReady, height, width }) => {
  const [style, setStyle] = useState({
    height,
    width,
    display: 'block',
  })
  const getImgWithAndHeight = (url) => {
    return new Promise((resolve, reject) => {
      var img = new Image()
      //      src
      img.src = url
      let set = null
      const onload = () => {
        if (img.width || img.height) {
          //      
          clearInterval(set)
          resolve({ width: img.width, height: img.height })
        }
      }
      set = setInterval(onload, 40)
    })
  }

  useEffect(() => {
    getImgWithAndHeight(imgUrl).then((size) => {
      const currentHeight = size.height * (width / size.width)
      setStyle({
        height: currentHeight,
        width: width,
        display: 'block',
      })
      onHeightReady(currentHeight)
    })
  }, [])
  return <img src={imgUrl} alt=''  style={style} />
}
그림 높이 를 가 져 오 는 구성 요 소 를 먼저 쓰 고 정시 순환 검 사 를 통 해 부모 구성 요소 에 높이 를 계산 합 니 다.

import React, { useState, useEffect, useRef } from 'react'
import styles from './index.scss'
import { AutoSizer } from 'react-virtualized/dist/commonjs/AutoSizer'
import { List  } from 'react-virtualized/dist/commonjs/List'

export default class DocumentStudy extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      list: [], 
      heights: [],
      autoWidth:900,
      autoHeight: 300
    }
  }

  handleHeightReady = (height, index) => {
    this.setState(
      (state) => {
        const flag = state.heights.some((item) => item.index === index)
        if (!flag) {
          return {
            heights: [
              ...state.heights,
              {
                index,
                height,
              },
            ],
          }
        }
        return {
          heights: state.heights,
        }
      },
      () => {
        this.listRef.recomputeRowHeights(index)
      },
    )
  }

  getRowHeight = ({ index }) => {
    const row = this.state.heights.find((item) => item.index === index)
    return row ? row.height : this.state.autoHeight
  }

  renderItem = ({ index, key, style }) => {
    const { list, autoWidth, autoHeight } = this.state
    if (this.state.heights.find((item) => item.index === index)) {
      return (
        <div key={key} style={style}>
          <img src={list[index].imgUrl}  alt='' style={{width: '100%'}}/>
        </div>
      )
    }

    return (
      <div key={key} style={style}>
        <ImgHeightComponent
          imgUrl={list[index].imgUrl}
          width={autoWidth}
          height={autoHeight}
          onHeightReady={(height) => {
            this.handleHeightReady(height, index)
          }}
        />
      </div>
    )
  }

  render() {
    const { list } = this.state
    return (
      <>
        <div style={{ height: 1000 }}>
          <AutoSizer>
            {({ width, height }) => (
              <List
                ref={(ref) => (this.listRef = ref)}
                width={width}
                height={height}
                overscanRowCount={10}
                rowCount={list.length}
                rowRenderer={this.renderItem}
                rowHeight={this.getRowHeight}
              />
            )}
          </AutoSizer>
        </div>
      </>
    )
  }
}
부모 구성 요 소 는 handle HeightReady 방법 을 통 해 모든 그림 의 높이 를 수집 하고 List 구성 요 소 를 호출 하 는 recomputeRow Heights 방법 을 변경 하여 구성 요소 에 높이 와 오프셋 을 다시 계산 하 라 고 알 립 니 다.여기까지 와 서 기본적으로 직면 한 문 제 를 해결 했다.
실제 효과

작은 매듭
현 재 는 react-virtualized 를 사용 하여 이미지 긴 목록 을 완성 할 뿐 구체 적 인 react-virtualized 내부 실현 은 더 연구 해 야 한다.
이상 은 react-virtualized 로 이미지 동적 높이 의 긴 목록 을 실현 하 는 상세 한 내용 입 니 다.react virtualized 긴 목록 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

좋은 웹페이지 즐겨찾기