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パッケージとしてデプロイされることが多い。

推薦する

LinuxにMySQLをインストールし、外部ネットワークアクセスを構成する例

設定手順1. DNSが設定されているかどうかを確認するDNSが設定されていない場合は、前の記事を参照...

角度コンテンツ投影の詳細な説明

目次単一コンテンツ投影マルチコンテンツ投影単一条件のコンテンツ投影アプリ-人物-htmlアプリ担当者...

Postman に基づく HTTP インターフェース テスト プロセスの分析

偶然、素晴らしい人工知能のチュートリアルを発見したので、みんなと共有せずにはいられませんでした。この...

高さ:100% が機能しないのはなぜですか?

高さ:100% が機能しないのはなぜですか?この知識は不人気ではありませんが、使用する際には混乱する...

純粋な CSS ヘッダーの実装コードを修正

純粋な CSS で固定ヘッダーを実装するのが難しい主な理由は 2 つあります。まず、最大のシェアを持...

docker-compose ネットワーク設定についての簡単な説明

ネットワーク使用チュートリアル公式サイト docker-compose.yml リファレンスドキュメ...

Mysql 複数データベースのバックアップ コード例

この記事は主にMysqlの複数データベースのバックアップのコード例を紹介します。この記事ではサンプル...

Vue の共通 A​​PI と高度な API の概要

目次次のチェックミックスイン$強制更新設定、削除フィルター指令その他の単純な共通プロパティとメソッド...

MySQL 5.7.17 圧縮パッケージのインストール不要の構成プロセス図

MySQL データベース管理ソフトウェアには、エンタープライズ エディションとコミュニティ エディシ...

HTML 選択オプションの基本的な理解と使用

JavaScript での HTML (選択オプション) の詳細な説明1. 基本的な理解:コードをコ...

Linux でのマルチスレッドにおけるフォークの紹介

目次質問:ケース(1)子スレッドを作成する前にフォークするケース(2)子スレッドを作成した後にフォー...

ウェブページのFOUC問題によるウェブページの混乱の解決策

FOUC は Flash of Unstyled Content の略で、FOUC と略されます。簡...

クラウド CentOS で Docker リモート サービス リンクを有効にするための実装手順

ここでは、dockerがインストールされたcentosサーバーを紹介し、リモートリンクサービスを開始...

VMwareでCentOSがインターネットにアクセスできない問題を素早く解決

昨日、VMware に CentOS7 をインストールしました。Tomcat パッケージを転送するた...

JSはプログレスバーのスムーズバージョンの詳細な計画を実装します

進捗バーがスムーズではないフロントエンドを学ぶ学生のほとんどは、オーディオプレーヤーやビデオプレーヤ...