react-virtualized を使用して、動的な高さを持つ画像の長いリストを実装する

react-virtualized を使用して、動的な高さを持つ画像の長いリストを実装する

バーチャルリストは、スクロールコンテナ要素の表示領域に応じて、データの一部を長いリストとしてレンダリングする技術です。仮想リストは、長いリストのシナリオでよく使用される最適化です。結局のところ、リストに何百ものサブ要素をレンダリングする人はほとんどいません。スクロール バーが水平または垂直にスクロールするときに、表示領域に要素をレンダリングするだけで十分です。

開発中に発生した問題

1. 長いリスト内の画像は、元の写真と同じ比率を維持する必要があります。垂直スクロール時に幅が変化しない場合、各画像の高さは動的になります。リスト項目の高さが変化すると、リスト項目と後続のすべてのリスト項目の位置情報に影響します。

2. 画像の幅と高さは、画像が読み込まれた後にのみ取得できます。

解決

react-virtualizedのリストコンポーネントを使用します。公式の例です。

'react' から React をインポートします。
'react-dom' から ReactDOM をインポートします。
'react-virtualized' から {List} をインポートします。

// データを文字列の配列としてリストします
定数リスト = [
  「ブライアン・ヴォーン」
  // 等々...
];

関数 rowRenderer({
  key, // 行の配列内の一意のキー
  index, // コレクション内の行のインデックス
  isScrolling, // リストは現在スクロール中です
  isVisible, // この行はリスト内に表示されます (つまり、オーバースキャンされた行ではありません)
  style, // 行に適用されるスタイル オブジェクト (配置するため)
}) {
  戻る (
    <div キー = {キー} スタイル = {スタイル}>
      {リスト[インデックス]}
    </div>
  );
}

// リストをレンダリングする
ReactDOM.render() は、
  <リスト
    幅={300}
    高さ={300}
    rowCount={リストの長さ}
    行の高さ={20}
    行レンダラー = {行レンダラー}
  />,
  document.getElementById('例')、
); 

rowHeight は各行の高さです。固定の高さまたは関数を渡すことができます。子要素の高さが変わるたびに、インデックスを指定した後、行の高さとオフセットを再計算するために recomputeRowHeights メソッドを呼び出す必要があります。

具体的な実装

const ImgHeightComponent = ({ imgUrl, onHeightReady, 高さ, 幅 }) => {
  const [スタイル、setStyle] = useState({
    身長、
    幅、
    表示: 'ブロック'、
  })
  const getImgWithAndHeight = (url) => {
    新しい Promise を返します ((resolve, reject) => {
      var img = 新しい画像()
      // 画像のsrcを変更する
      img.src = URL
      set = null とする
      定数onload = () => {
        if (画像の幅 || 画像の高さ) {
          //画像の読み込みが完了しました clearInterval(set)
          解決({ 幅: img.width, 高さ: img.height })
        }
      }
      設定 = setInterval(onload, 40)
    })
  }

  使用効果(() => {
    getImgWithAndHeight(imgUrl).then((サイズ) => {
      定数 currentHeight = size.height * (幅 / size.width)
      スタイルを設定する({
        高さ: 現在の高さ、
        幅: 幅、
        表示: 'ブロック'、
      })
      onHeightReady(現在の高さ)
    })
  }, [])
  <img src={imgUrl} alt='' style={style} /> を返します
}

まず、画像の高さを取得するコンポーネントを記述し、タイムループ検出を通じて高さを取得して計算し、それを親コンポーネントに渡します。

'react' から React、{useState、useEffect、useRef} をインポートします。
'./index.scss' からスタイルをインポートします
'react-virtualized/dist/commonjs/AutoSizer' から { AutoSizer } をインポートします。
'react-virtualized/dist/commonjs/List' から {List} をインポートします。

デフォルトのクラスDocumentStudyをエクスポートし、React.Componentを拡張します。
  コンストラクタ(props) {
    スーパー(小道具)
    この状態 = {
      リスト: [], 
      高さ: [],
      自動幅:900、
      自動高さ: 300
    }
  }

  handleHeightReady = (高さ, インデックス) => {
    this.setState() は、
      (状態) => {
        const flag = state.heights.some((item) => item.index === index)
        if (!フラグ) {
          戻る {
            高さ: [
              ...州の高さ、
              {
                索引、
                身長、
              },
            ]、
          }
        }
        戻る {
          高さ: state.heights、
        }
      },
      () => {
        this.listRef.recomputeRowHeights(インデックス)
      },
    )
  }

  getRowHeight = ({ インデックス }) => {
    定数 row = this.state.heights.find((item) => item.index === インデックス)
    行を返します? row.height: this.state.autoHeight
  }

  renderItem = ({ インデックス、キー、スタイル }) => {
    const { リスト、自動幅、自動高さ } = this.state
    if (this.state.heights.find((item) => item.index === index)) {
      戻る (
        <div キー = {キー} スタイル = {スタイル}>
          <img src={list[index].imgUrl} alt='' style={{width: '100%'}}/>
        </div>
      )
    }

    戻る (
      <div キー = {キー} スタイル = {スタイル}>
        <画像高さコンポーネント
          imgUrl={リスト[インデックス].imgUrl}
          幅={自動幅}
          高さ={自動高さ}
          onHeightReady={(高さ) => {
            this.handleHeightReady(高さ、インデックス)
          }}
        />
      </div>
    )
  }

  与える() {
    const { リスト } = this.state
    戻る (
      <>
        <div スタイル = {{ 高さ: 1000 }}>
          <オートサイザー>
            {({ 幅, 高さ }) => (
              <リスト
                ref={(ref) => (this.listRef = ref)}
                幅={幅}
                高さ={高さ}
                オーバースキャン行数={10}
                rowCount={リストの長さ}
                rowRenderer={this.renderItem}
                行の高さ={this.getRowHeight}
              />
            )}
          </オートサイザー>
        </div>
      </>
    )
  }
}

親コンポーネントは、handleHeightReady メソッドを通じてすべての画像の高さを収集し、高さが変化するたびに List コンポーネントの recomputeRowHeights メソッドを呼び出して、コンポーネントに高さとオフセットを再計算するように通知します。この時点で、遭遇した問題は基本的に解決されました。

実績

まとめ

現在、長い画像リストを実装するために react-virtualized のみを使用しています。 react-virtualized の具体的な内部実装については、さらに調査する必要があります。

上記は react-virtualized を使用して動的な画像の長いリストを実装する詳細です。 react virtualized の長いリストの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • React Native での ScrollView コンポーネント カルーセルと ListView レンダリング リスト コンポーネントの使用例の分析
  • Reactモバイル端末は左にスワイプしてリストを削除するサンプルコードを実装します
  • React Native カスタム プルダウン リフレッシュ プルアップ ロード済みリストの例
  • React Native インデックス付き都市リスト コンポーネントのサンプル コード
  • Reactはクリックするとリスト内の対応する項目が削除されるように実装します

<<:  CentOS に PHP5 をインストール、PHP をアンインストール、PHP7 をインストールするチュートリアル

>>:  MySQL Innodbインデックスの原理の詳細な説明

推薦する

HarborをベースにしたDocker専用倉庫の構築方法

目次1. ハーバーの紹介1. ハーバーが民間倉庫を建設3. 港湾の維持管理4. Harborユーザー...

見落としがちなVue.jsのAPIを詳しく解説

目次次のチェックv-model 構文シュガー.sync 修飾子$セット計算プロパティセット要約する次...

JavaScriptはスライダーを介してWebページの色を変更することを実装します

みなさんこんにちは、今日はウェブフロントエンドのHTMLを見ていたら、inputタグのtype属性が...

MySQLデータベースでゼロ値を含む日付の問題について簡単に説明します

デフォルトでは、MySQL は日付に 0 値を挿入することを受け入れますが、実際には日付の 0 値に...

MySQLデータベースでの値の追加、変更、削除、クリアの例

3. MySQLデータ管理最初の方法:お勧めできません。複雑そうです -- 学生テーブルの grad...

React で遅延読み込みを使用して最初の画面の読み込み時間を短縮する方法

目次使用インストールルーティングでどのように使用しますか?読み込み速度の比較最近、中間およびバックエ...

Nginx+tomcat ロードバランシングクラスタの実装方法

実験環境は以下のとおりですここでは、4 台のサーバー (1 台の nginx、負荷用の 2 台の t...

Hyper-V インストール CentOS 8 の問題の分析

CentOS 8 がリリースされてから随分経ちました。Linux 仮想マシンをいじっている人間として...

Vueフィルターの詳細な説明

<本文> <div id="ルート"> <h2&...

Mariadb リモート ログイン構成と問題解決

序文:インストール プロセスについては詳しく説明しません。問題に直接触れましょう。MySQL のリモ...

MySQLでテーブル名を変更する方法と注意すべき点

目次1. テーブル名を変更する方法2. 注記要約: 1. テーブル名を変更する方法RENAME TA...

vue.config.js パッケージ最適化構成

Baiduの情報は多様すぎて目が回ります。心配しないでください。私はあなたのためにそれを体験しました...

Vueのキーボードイベントの詳細な説明

目次共通キーエイリアスエイリアスが指定されていないキーシステム修飾キーカスタムキーエイリアス要約する...

Bツリー挿入プロセスの概要

前回の記事 https://www.jb51.net/article/154153.htm では、B...

HTML+CSS+JavaScript でシンプルな三目並べゲームを作成する

目次HTMLの実装CSSを追加Javascript部分の実装デモアドレス HTMLの実装まず、hea...