WeChatアプレットは固定ヘッダーとリストテーブルコンポーネントを実装します

WeChatアプレットは固定ヘッダーとリストテーブルコンポーネントを実装します

必要:

WeChatアプレットは固定ヘッダーと固定列のテーブルコンポーネントを実装します(若干の変更を加えることでモバイル端末にも適用可能)

機能ポイント

  • ソートテーブル
  • ヘッダーは固定できる
  • 最初の列は固定されています(指定した列の左側と右側を固定するように構成するように最適化できます)
  • ページめくり(上に引っ張って読み込む)の監視

レンダリング

実装のアイデア

スクロールの連動を実装するために、3 つの ScrollView を使用することを考え始めました。ヘッダーと列が固定されている場合、テーブルの内容がスクロールすると、ヘッダーと列もそれに応じてスクロールする必要があります。デモを作成した後、1 つの ScrollView の位置情報を監視して他の 2 つの ScrollView の位置を設定するのは非常に面倒で、エクスペリエンスが非常に悪いことがわかりました。position:sticky; を使用して、ヘッダーをテーブルの上部に固定し、各行の最初の要素を現在の行の左側に固定します。

発生した問題:

  • テーブルを左にスライドすると、固定列は 1 画面分スライドした後、画面外にスライドします。解決策: テーブルの幅を動的に設定します。原則: スライド アウトする理由は、行全体が画面からスライド アウトし、スティッキーが行全体の左側を基準に配置されるためです。
  • テーブルの高さを 100% に設定すると、useReachBottom プルアップ監視が失敗します。テーブルの高さを高く設定すると、固定ヘッダーが失敗します。解決策: ScrollViewを使用してテーブルを折り返し、onScrollToLowerを使用して読み込みをリッスンします。

具体的なコード(react\taro3.0)

インデックス.tsx

/**
 * スライド可能、固定ヘッダー、固定列のテーブル コンポーネント* @example <Table data={data} dataAttribute={dataAttribute} sortTypeChange={sortTypeChange} handleRow={toDetails}/>
 */

'react' から React、{useState、useMemo、useEffect} をインポートします。
'classnames' から classNames をインポートします

// コンポーネント
'@tarojs/components' から { View, Text, ScrollView } をインポートします。

// ユーティリティ
'@/utils/util' から { noop } をインポートします

// スタイル
'./index.module.less' からスタイルをインポートします

インターフェース DataAttributeItem {
  タイトル: 文字列
  キー: 文字列 | 数値
  ソートキー?: 文字列 | 数値
}

インターフェースProps{
  データ: 配列<任意>
  データ属性: 配列<データ属性項目>
  sortTypeChange?: (sort_item_id: 任意、sort_desc: ブール値) => void
  handleRow?: (データ: 任意) => void
  handleScrollToLower?: (e: 任意) => void
}

デフォルトの関数Table(props: Props)をエクスポートします。
  const { data、dataAttribute、sortTypeChange = noop、handleRow = noop、handleScrollToLower = noop } = props
  const [isSortDesc, setIsSortDesc] = useState<boolean>(true)
  const [sortIndex, setSortIndex] = useState<数値>(1)
  const テーブル幅 = useMemo(() => {
    `${(dataAttribute.length * 148 + 48)}rpx` を返します
  }, [データ属性])

  const テーブルの高さ = useMemo(() => {
    `${((data.length + 1) * 96)}rpx` を返します
  }、 [データ])

  const ハンドルソートアイテム = (属性アイテム、属性インデックス) => {
    属性インデックス === 0 の場合 {
      戻る
    }
    定数 beforeIndex = sortIndex
    定数sortKey = attrItem.sortKey
    dataAttribute.map((item, index)=>{
      if (item.sortKey === sortKey) {
        if (beforeIndex === インデックス) {
          setIsSortDesc(!isSortDesc)
        } それ以外 {
          setSortIndex(インデックス)
          並べ替え順序を設定します(true)
        }
      }
    })
  }

  使用効果(()=>{
    定数 sort_desc = isSortDesc
    const sort_item_id = データ属性[ソートインデックス].sortKey
    ソートタイプ変更(ソート項目ID、ソート順序)
  },[ソートインデックス、isSortDesc])


  戻る (
    <ScrollView className={styles['table']} scrollY scrollX onScrollToLower={handleScrollToLower}>
      <View className={styles['sticky-box']} style={{height: tableHeight}}>
        <View className={styles['grey-box']} style={{width: tableWidth, position: 'sticky'}}/>
        <View className={styles['table__head']} style={{width: tableWidth, position: 'sticky'}}>
          {dataAttribute.map((attrItem, attrIndex) => (
            <View className={styles['table__head__td']} key={attrIndex} onClick={()=>handleSortItem(attrItem, attrIndex)}>
              <テキスト
                クラス名={クラス名({
                  [スタイル['table__head__td__text']]: true,
                  [styles['table__head__td__text-active']]: sortIndex === attrIndex、
                })}
                キー={属性インデックス}
              >{attrItem.title}</テキスト>
              {attrIndex !== 0 && <ビュー
                クラス名={クラス名({
                  [styles['table__head__td__sorter-indicate']]: true,
                  [styles['table__head__td__sorter-indicate--asc-active']]: sortIndex === attrIndex && !isSortDesc,
                  [styles['table__head__td__sorter-indicate--desc-active']]: sortIndex === attrIndex && isSortDesc
                })}
              }}}
            </表示>
          ))}
        </表示>
        {data.map((データ項目、データインデックス) => (
          <View className={styles['table__row']} key={dataIndex} style={{width: tableWidth}} onClick={() => handleRow(dataItem)}>
            {dataAttribute.map((attrItem, attrIndex) => {
              戻る (
                <Text className={styles['table__row__td']} key={attrIndex}>{dataItem[attrItem.key] || '-'}</Text>
              )
            })}
          </表示>
        ))}
      </表示>
    </スクロールビュー>
  )
}

インデックスモジュール

@import '~@/assets/style/mixins/ellipsis.less';
ページ{
  フォントサイズ: 26rpx;
  行の高さ: 60rpx;
  色: #222;
  高さ: 100%;
  幅: 100%;
}
.grey-box{
  高さ: 10rpx;
  上: 0;
  背景: #f8f8f8;
  zインデックス: 100;
}
。テーブル{
  位置: 相対的;
  オーバーフロー: スクロール;
  幅: 100%;
  高さ: 100%;
  オーバーフロー: スクロール;
  &__頭{
    位置: 相対的;
    高さ: 96rpx;
    空白: ラップなし;
    // 位置: スティッキー;
    上: 10rpx;
    zインデックス: 100;
    高さ: 88rpx;
    フォントサイズ: 24rpx;
    行の高さ: 88rpx;
    色: #aaabbd;
    背景色: #f8f8f8;
    下部境界線: 2rpx 実線 #ecf1f8;
    背景色: #fff;
    空白: ラップなし;
    ディスプレイ: フレックス;
    &__td{
      .ellipsis();
      幅: 148rpx;
      // パディング右: 40rpx;
      ディスプレイ: フレックス;
      コンテンツの配置: flex-start;
      アイテムの位置を中央揃えにします。
      背景色: #fff;
      位置: 相対的;
      ボックスのサイズ: 境界線ボックス;
      &:n番目の子(1) {
        左パディング: 24rpx;
        幅: 154rpx;
        右マージン: 40rpx;
        位置: 固定;
        zインデックス: 10;
        左: 0;
      }
      &__文章{
        表示: インライン;
        &-アクティブ{
          色: #6d70ff;
        }
      }
      &__sorter-indicate{
        幅: 24rpx;
        高さ: 24rpx;
        表示: インラインブロック;
        背景繰り返し: 繰り返しなし;
        背景サイズ: 100% 100%;
        背景画像: url('https://icon1.png');
        &--asc-アクティブ {
          背景画像: url('https://icon2.png');
        }
        &--desc-active {
          背景画像: url('https://icon3.png');
        }
      }
    }
  }
  &__行{
    位置: 相対的;
    高さ: 96rpx;
    空白: ラップなし;
    ディスプレイ: フレックス;
    コンテンツの配置: flex-start;
    アイテムの位置を中央揃えにします。
    下部境界線: 2rpx 実線 #ecf1f8;
    &__td{
      // .ellipsis();
      オーバーフロー: スクロール;
      空白: ラップなし;
      幅: 148rpx;
      // パディング右: 40rpx;
      表示: インラインブロック;
      背景色: #fff;
      位置: 相対的;
      ボックスのサイズ: 境界線ボックス;
      フォントサイズ: 26rpx;
      行の高さ: 96rpx;
      &:n番目の子(1) {
        右マージン: 40rpx;
        左パディング: 24rpx;
        幅: 154rpx;
        位置: 固定;
        zインデックス: 10;
        左: 0;
      }
    }
  }
}

特定のコード(ミニプログラムネイティブ)

<ScrollView class="table" scroll-x scroll-y bindscrolltolower="handleScrollToLower">
  <View class="sticky-box" style="height:{{tableHeight}}rpx;">
    <View class="table__head" style="width:{{tableWidth}}rpx;">
      <View class="table__head__td" wx:for="{{dataAttribute}}" wx:key="attrIndex" wx:for-index="attrIndex" wx:for-item="attrItem">
        <テキスト
          クラス="table__head__td__text"
        >{{attrItem.title}}</テキスト>
      </表示>
    </表示>
    <View class="table__row" wx:for="{{data}}" wx:key="dataIndex" wx:for-index="dataIndex" wx:for-item="dataItem" style="width:{{tableWidth}}rpx;">
      <Text class="table__row__td" wx:for="{{dataAttribute}}" wx:key="dataIndex" wx:for-index="attrIndex" wx:for-item="attrItem">{{dataItem[attrItem.key] || '-'}}</Text>
    </表示>
  </表示>
</スクロールビュー>
const アプリ = getApp()
ページ({
  データ: {
    データ: [
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
      {
        123,
        b: 456,
        c: 489,
        d: 789,
        e: 458,
        女性: 789
      },
    ]、
    データ属性: [
      {
        タイトル: 「最初の列」、
        キー: 'a'
      },
      {
        タイトル: '列2'、
        キー: 'b'
      },
      {
        タイトル: '列3'、
        キー: 'c'
      },
      {
        タイトル: 'コラム4'、
        キー: 'd'
      },
      {
        タイトル: 'コラム5'、
        キー: 'e'
      },
      {
        タイトル: 「コラム6」
        キー: 'f'
      }
    ]、
    テーブルの高さ: (20 + 1) * 96,
    テーブル幅: 200 * 6 + 60
  }
})
ページ{
  フォントサイズ: 26rpx;
  行の高さ: 60rpx;
  色: #222;
  高さ: 100%;
  幅: 100%;
}
。テーブル{
  表示: ブロック;
  位置: 相対的;
  オーバーフロー: スクロール;
  幅: 100%;
  高さ: 100%;
}
.sticky-box{
}
.table__head{
  高さ: 96rpx;
  空白: ラップなし;
  位置: 固定;
  上: 0rpx;
  zインデックス: 100;
  高さ: 88rpx;
  フォントサイズ: 24rpx;
  行の高さ: 88rpx;
  色: #aaabbd;
  背景色: #f8f8f8;
  下部境界線: 2rpx 実線 #ecf1f8;
  背景色: #fff;
  空白: ラップなし;
  ディスプレイ: フレックス;
}
.table__head__td{
  幅: 200rpx;
  ディスプレイ: フレックス;
  コンテンツの配置: flex-start;
  アイテムの位置を中央揃えにします。
  背景色: #fff;
  ボックスのサイズ: 境界線ボックス;
  位置: 相対的;
  オーバーフロー: 非表示;
  空白: ラップなし;
  -o-テキストオーバーフロー:省略記号;
  テキストオーバーフロー: 省略記号;
}
.table__head__td:n番目の子(1) {
  左パディング: 24rpx;
  幅: 260rpx;
  右マージン: 40rpx;
  位置: 固定;
  zインデックス: 101;
  左: 0rpx;
}
.table__head__td__text{
  表示: インライン;
}
.table__row{
  位置: 相対的;
  高さ: 96rpx;
  空白: ラップなし;
  ディスプレイ: フレックス;
  コンテンツの配置: flex-start;
  アイテムの位置を中央揃えにします。
  下部境界線: 2rpx 実線 #ecf1f8;
}
.table__row__td{
  オーバーフロー: スクロール;
  空白: ラップなし;
  幅: 200rpx;
  表示: インラインブロック;
  背景色: #fff;
  ボックスのサイズ: 境界線ボックス;
  フォントサイズ: 26rpx;
  行の高さ: 96rpx;
  位置: 相対的;
  オーバーフロー: 非表示;
  空白: ラップなし;
  -o-テキストオーバーフロー:省略記号;
  テキストオーバーフロー: 省略記号;
}
.table__row__td:n番目の子(1) {
  右マージン: 40rpx;
  左パディング: 24rpx;
  幅: 260rpx;
  位置: 固定;
  zインデックス: 10;
  左: 0;
}

要約する

WeChatミニプログラムで固定ヘッダーとテーブルコンポーネントを実装する方法に関するこの記事はこれで終わりです。WeChatミニプログラムの固定ヘッダーに関する関連コンテンツの詳細については、123WORDPRESS.COMで以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後も123WORDPRESS.COMを応援してください。

<<:  MySQLにおけるACIDトランザクションの実装原理の詳細な説明

>>:  SSMプロジェクトは、ホットデプロイメント構成を実装するためにTomcatとMavenを使用してWARパッケージとしてデプロイされることが多い。

推薦する

数千万のMySQLデータ量を素早くページ分割する方法

序文バックエンド開発では、一度に大量のデータがロードされ、メモリやディスク IO のオーバーヘッドが...

ウェブページ内の 2 つのボックス モデル (W3C ボックス モデル、IE ボックス モデル)

Web ページ ボックス モデルには 2 種類あります。 1: 標準 W3C ボックス モデル。2:...

サーバー上でjupyterノートブックを実行する問題を解決する

目次サーバーはjupyterノートブックを実行します仮想環境次にファイアウォールをオフにしますJup...

Linux 環境に MySQL 8.0 をインストールするプロセスの紹介

目次序文1. Linux は yum ソースを変更します (MYSQL のインストールが遅い場合は試...

Mysql での結合操作

結合の種類1. 内部結合: 結合関係を持つ 2 つのテーブル内のフィールドは、結合関係を満たすレコー...

VMwareのCentosシステムでNavicatがMySQLサーバーに接続できない問題を解決します

ホスト 'xxxx' はこの MySQL サーバーに接続できませんエラー: 1130...

nginx + php の「入力ファイルが指定されていません」の解決策

本日、ローカル開発環境で突然「入力ファイルが指定されていません」というエラーが発生してしまいました。...

MySQL の lru リンク リストの簡単な分析

1. 従来のLRUリンクリストについて簡単に説明するLRU:最も最近使われなかったものLRU リンク...

Vue cli開発に基づく外部コンポーネントVantのデフォルトスタイルの変更の詳細な説明

目次序文1. 少ない2. コンポーネントをインポートする3. 設定ファイルを変更するステップ1: l...

MySQL 8 の新機能: 非表示のインデックス

背景インデックスは諸刃の剣です。クエリ速度は向上しますが、DML 操作も遅くなります。結局のところ、...

Dockerコンテナシェルスクリプトの実行ステータスを監視する方法

シナリオ会社のプロジェクトはDockerでデプロイされています。原因不明ですが、コンテナが時々停止し...

FirefoxでCookieとお気に入りをインポートおよびエクスポートする方法

Firefox は、多くの拡張機能とプラグインを備えた、よく使用されるブラウザです。IE に比べて多...

MySQL 5.7 に組み込まれているストレス テストの mysqlslap コマンドと構文の詳細な説明

序文mysqlslap は、MySQL サーバーへのクライアント負荷をシミュレートし、各ステージの時...

MySQL テーブルの読み取り、書き込み、インデックス作成、その他の操作の SQL ステートメントの効率最適化の問題を分析します。

前回は、Explain 実行プランの表示、インデックスの分析など、MySQL での SQL クエリの...

vscodeカスタムvueテンプレートの実装

vscode エディタを使用して vue テンプレートを作成すると、新しい vue ファイルを作成す...