Vue3+el-tableは行と列の変換を実現します

Vue3+el-tableは行と列の変換を実現します

行と列の変換

行と列の変換の問題はなぜ発生するのでしょうか?ユーザーが見たいのは複数の列を持つ大きなフォームですが、データベースには「単一列」のデータしか保存されていないためです。そのため、顧客がより便利かつ明確に見ることができるように変換する必要があります。

このような行と列の変換をサポートできる SQL を記述する方法はありますが、記述が複雑で理解しにくいです。
そのため、個人的には、バックエンドのパフォーマンス リソースを節約できるため、フロントエンドで変換操作を実装することを好みます。

ここでは、具体的な実装方法を示すために、トランスクリプトを例に挙げます。

トランスクリプトの構成を分析する

この好き嫌いの問題は、皆さんもよくご存知でしょう。これは、行と列の変換を必要とする典型的なシナリオです。
トランスクリプトがどのようなものか確認してみましょう: (画像はインターネットから引用したもので、著作権を侵害している場合は削除してください)

トランスクリプト

分析後、次の基本要素が得られます。

  • 科目:中国語、数学、物理、化学など。列の数を決定する
  • 生徒:行数を決定する
  • 学年・クラス:1年生、1年、2年など分類基準
  • 試験:中間試験、期末試験など分類基準
  • 結果: データの内容を決定します。

要素の分類:

  • 分類基準: 同じカテゴリのデータを大きなフォームに集約し、大きなフォームを生成するためのクエリ条件を指します。
  • 件名: 列の数を決定します。件名が多いほど、列の数も多くなります。
  • 生徒: 行数を決定します。生徒の数が多いほど、行数も多くなります。

データベースの設計を見てみましょう。一般的には、いくつかの基本テーブルとスコアテーブルが設計されます。

  • 件名表
  • 学生テーブル
  • クラススケジュール
  • 試験スケジュール
  • 結果

スペースが限られているため、特定の分野については紹介しません。すべてを紹介するのは非常に複雑になります。

vue3 + el-table で作成されたトランスクリプト

行と列の変換後のトランスクリプト

科目、生徒、合計点、平均点、最高点、最低点、順位などがすべて表示されます。さまざまな並べ替えオプションも可能です。これがどのように実現されるか見てみましょう。

フロントエンドシミュレーションデータ

フロントエンドでデータをシミュレートしてみましょう。 (簡易モード)

// 件名 - 列を決定する const subject = [
  { id: 1, 名前: '数学' },
  { id: 2、名前: '中国語' }、
  { id: 3, 名前: '物理学' },
  { id: 4、名前: '化学' }
]

// 学生 - 行を決定する const student = [
  { id: 1, name: '张三' },
  { id: 2, 名前: 'Li Si' },
  { id: 3, 名前: '王五' },
  { id: 4、名前: '趙劉' }
]

// クラス - const に基づく分類 classes = [
  { id: 1, name: '1年生1年生' },
  { id: 2、名前: 'クラス2、グレード1' }
]

//試験 - 分類基準 const exam = [
  { id: 1, name: '中間試験' },
  { id: 2、名前: '期末試験' }
]

// スコア - コンテンツを決定する const reportCard = [
  //シリアル番号 試験ID クラスID 学生ID 科目ID スコア { id: 1, examId: 1, classId: 1, studentId: 1, subjectId: 1, score: 100 },
  { id: 2、試験 ID: 1、クラス ID: 1、学生 ID: 1、科目 ID: 2、スコア: 98 },
  { id: 3、試験ID: 1、クラスID: 1、学生ID: 1、科目ID: 3、スコア: 90 },
  { id: 4、試験ID: 1、クラスID: 1、学生ID: 2、科目ID: 1、スコア: 90 },
  { id: 5、試験ID: 1、クラスID: 1、学生ID: 2、科目ID: 2、スコア: 90 },
  { id: 6、試験ID: 1、クラスID: 1、学生ID: 2、科目ID: 3、スコア: 40 },
  { id: 7、試験ID: 1、クラスID: 1、学生ID: 3、科目ID: 1、スコア: 30 },
  { id: 8、試験ID: 1、クラスID: 1、学生ID: 3、科目ID: 2、スコア: 90 },
  { id: 8、試験ID: 1、クラスID: 1、学生ID: 3、科目ID: 3、スコア: 40 },
  { id: 9、試験ID: 1、クラスID: 1、学生ID: 4、科目ID: 1、スコア: 64 },
  { id: 8、試験ID: 1、クラスID: 1、学生ID: 4、科目ID: 2、スコア: 90 },
  { id: 9、試験 ID: 1、クラス ID: 1、学生 ID: 4、科目 ID: 3、スコア: 70 }
]

el-tableを使用してトランスクリプトを生成する

Element-plus は、並べ替え、幅の調整、色の設定、フィルタリングなどの多くの基本機能を実現できる非常に強力なテーブル コンポーネント el-table を提供します。次に、このコンポーネントを使用してトランスクリプトを実装できます。

ヘッダーを決定する

行と列の変換の主な特徴は、テーブル ヘッダー (列の数) が固定されておらず、動的に生成する必要があることです。
トランスクリプトを例にとると、表のヘッダーの列数は件名によって決まります。件名が多いほど、ヘッダーの数も多くなります。

まず、el-table の要件に従ってテーブル ヘッダーを設定します。

/**
 * 科目に基づいて表のヘッダーを作成します* * 学生ID、名前、[科目]、合計点、平均点、順位*/
const createTableHead = () => {
  // 生徒を追加 const head = [
  {
    プロパティ: 'id',
    ラベル: '学生番号'、
    幅: 120
  },
  {
    プロパティ: '名前',
    ラベル: '名前',
    幅: 120
  }]

  // 件名を追加 for (const key in subject) {
    const sub = subject[キー]
    head.push({
      プロパティ: 'sub_' + sub.id,
      ラベル: サブ名、
      幅: 120
    })
  }

  head.push({
    プロパティ: 'totalScore',
    ラベル: '合計スコア'、
    幅: 120
  })
  head.push({
    プロパティ: 'averageScore',
    ラベル: '平均スコア'、
    幅: 120
  })
  head.push({
    プロパティ: 'ランキング'、
    ラベル: 'ランク'、
    幅: 120
  })
  
  リターンヘッド
}

ここには 2 種類のヘッダーがあり、1 つは固定で、もう 1 つは件名に基づいて動的に生成されます。
私たちは、まず固定列を直接追加し、次にサブジェクトを走査して動的な列を追加するという、単純で大まかなアプローチを採用しています。

データを決定する

テーブル ヘッダーが決定したら、データ部分を決定し、行と列の変換を正式に開始する必要があります。
el-table のニーズに応じてデータ形式を定義しましょう。

{
  id: 1,
  名前: '張三'、
  サブ_1: 100,
  サブ_2: 100,
  ...
  合計スコア: 200,
  平均スコア: 100,
  ランキング: 1
}

中間にはさまざまなサブジェクトが存在する可能性があり、属性の命名規則は、プレフィックス「sub_」+ サブジェクト ID です。
これにより、後でデータを追加するのが容易になります。

成績表を走査してデータを入力します。

/**
 * 行と列の変換 */
定数 rowToCol = () => {
  // オブジェクトベースのスコアリスト const _code = {}
  // 配列形式のスコアのリスト const _arr = []

  // レポートカードを走査します for (const key in reportCard) {
    const rep = reportCard[キー]
    if(typeof _code[rep.studentId] === 'undefined') {
      // レコードがありません。生徒の成績の行を作成し、固定列 data_code[rep.studentId] = { を追加します。
        id: rep.studentId, // 学生ID
        name: (student.filter((item)=>item.id === rep.studentId)[0] || {name:''}).name, // ID に基づいて生徒の名前を取得します totalScore: 0, // 各科目における生徒の合計スコア。後で変更されます averageScore: 0, // 各科目における生徒の平均スコア。後で変更されます ranking: 1 // ランキング。後で変更されます }
    }
    // 各科目のスコアを記録する_code[rep.studentId]['sub_' + rep.subjectId] = rep.score
  }

  // 下記のように合計スコアと平均スコアを計算します // 下記のようにランキングを計算します return _arr
}

成績証明書データを走査し、まず学生 ID に基づいてオブジェクトを作成し、次に科目に基づいて各科目の成績を決定します。

生徒の合計点と平均点を計算する

通常、成績証明書には、生徒の合計スコアと平均スコアも記載する必要があります。成績を走査して、合計スコアと平均スコアを計算できます。

  ...
  // 合計スコアと平均スコアを計算します for(const key in _code) {
    const コード = _code[キー]
    // 主題を走査する let total = 0
    ave = 0とする
    カウントを 0 にする
    for (const キー in subject) {
      const fenshu = code['sub_' + subject[key].id]
      if (typeof fenshu !== 'undefined') {
        // スコアがあるので、合計スコアと平均スコアの数を計算します++
        合計 += フェンシュ
        ave = Math.floor(total / count * 10) / 10 // 小数点第1位を保持します。
        // 小数点以下2桁を保持したい場合は、(total / count).toFixed(2) とします。
      }
    }
    code.totalScore = 合計
    code.averageScore = 平均
    //オブジェクトデータを配列に変換する data_arr.push(code)
  }

ランキングを計算する

トランスクリプトができたので、ランキングを作成する必要があります。
ランキングが必要ない場合は、この手順をスキップできます。

  _ranking = 0 とします
  _arr.sort((a, b) => {
    // 合計スコアの逆順に b.totalScore - a.totalScore を返す
  }).forEach((項目) => {
    // ランキングを設定する _ranking++
    _arr.find((a) => a.id === item.id).ranking = _ranking
  })


各科目の平均点を計算します。

これも一般的な要件です。
el-table は、科目の平均スコアを達成するために使用できる自動合計機能とカスタム合計方法を提供します。

以下は公式サイトで紹介されている方法です。本来は合計を出すためのものですが、少し手を加えることで科目の平均点を出すことができます。

 // 各科目の平均スコアを計算する let i = 0
const getSummaries = (パラメータ) => {
  私は++
  (i < 7) の場合 [] を返す

  const {列、データ} = param;
  定数の合計 = [];
  
  columns.forEach((列, インデックス) => {
    (インデックス === 0)の場合{
      sums[index] = '平均スコア'
      戻る
    }
    const values ​​= data.map(item => Number(item[column.property]));
    if (!values.every(値 => isNaN(値))) {
      sums[index] = values.reduce((prev, curr) => {
        定数値 = Number(curr)
        if (!isNaN(値)) {
          前へ + 次へ
        } それ以外 {
          前へ戻る
        }
      }, 0);
      sums[index] = Math.floor(sums[index] / values.length * 10) / 10
    } それ以外 {
      sums[index] = 'N/A';
    }
  })
  
  合計を返す

調べてみると、この関数は 7 回呼び出されることがわかりましたが、この回数は行数や列数とは関係ないようです。
さらに、最初の数回の返品は効果がなく、最後の返品のみが有効になるため、判定が追加されます。

各科目の最高点と最低点を記録する

トランスクリプトでは、科目の最高点や最低点など、さまざまなデータを計算することもできます。
一般的に、これらの統計データにも注目することができます。同様に、ニーズに合わせてカスタムの合計方法を使用することもできます。getSummaries を改善してみましょう。

// 各科目の平均スコア、最高スコア、最低スコアを計算します。const getSummaries = ({ columns }) => {
  私は++
  (i < 7) の場合 [] を返す

  定数の合計 = [];
   
  columns.forEach((item, index) => {
    (item.property.indexOf('sub_') >= 0 )の場合{
      定数 subjectId = item.property.replace('sub_', '')*1
      // 件名、平均を計算します。ave = 0
      合計を0とする
      最大値を0とする
      最小値を99999とする
      const _arr = reportCard.filter((r) => r.subjectId === subjectId)
      _arr.forEach((アイテム、インデックス) => {
        sum += item.score // 合計 if (max < item.score) max = item.score // 最高スコアを記録 if (min > item.score) min = item.score // 最低スコアを記録 })
      _arr.length === 0 の場合 {
        sums[index] = '-' // スコアなし} else {
        // 平均スコアを計算する ave = Math.floor(sum/_arr.length * 10) / 10
        合計[インデックス] = `${ave}(${max}-${min})`
      }
    } それ以外 {
      // 計算しない sums[index] = ''
    }
  })
  sums[0] = '統計'
  合計を返す

}

今回はreportCardを直接使用して平均スコア、最高スコア、最低スコアを計算します。
同様に、テストに合格した人数や各セグメントの人数もカウントできます。

並べ替え機能を追加

これは el-table の組み込み関数なので、追加するだけです。

<el-テーブル
    :data="テーブルデータ"
    スタイル="幅: 100%;高さ: 300px;"
    :default-sort = "{prop: 'totalScore', order: 'descending'}"
    :row-class-name="テーブル行クラス名"
    国境
    概要を表示
    :summary-method="getSummaries"
  >
    <el-テーブル列
      v-for="(item, index) in tableHead"
      :key="'s'+ インデックス"
      修理済み
      並べ替え可能
      :prop="アイテム.prop"
      :label="アイテム.ラベル"
      :width="アイテムの幅">
    </el-table-column>
  </el-table>

el-table プロパティ設定。 default-sort デフォルトでは、ランキングは合計スコアの降順で表示されます。

色の区別を強める

平均スコアが 60 未満のものを強調表示したい場合はどうすればよいでしょうか? el-table も機能を提供しているので、判断して CSS を設定するだけです。

// 色 const tableRowClassName = ({row, rowIndex}) => {
  if (row.averageScore < 60) { // 平均スコアが不合格の学生は 'warning-row' を返します。
  } else if (row.averageScore > 95) { // 平均スコアが 95 を超える学生は 'success-row' を返します。
  }
  戻る '';
}

ソースコード
https://gitee.com/naturefw/nf-vite2-element

まとめ

アドバンテージ:

  • バックエンドは行と列の変換を実行する必要がなく、基本データのみを提供すればよく、バックエンドのパフォーマンス リソースを節約できます。
  • 機能は非常に包括的で、基本的に考えられるものはすべて含まれています。

欠点:

  • 汎用的な形式にはなっていませんし、その他の行と列の変換要件には依然としてコードの記述が必要です。

これで、行と列の変換を実現する vue3+el-table に関するこの記事は終了です。vue3 の行と列の変換に関するより関連性の高いコンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、次の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vue3 テーブルコンポーネントの使用

<<:  select count() と select count(1) の違いと実行方法

>>:  Nginx ロケーション設定(ロケーションのマッチング順序)の詳細な説明

推薦する

HTMLフォームアプリケーションにはチェックボックスとラジオボタンの使用が含まれます

チェックボックスやラジオボタンの使用を含むコードをコピーコードは次のとおりです。 <!DOCT...

Vue3 コンパイルプロセス - ソースコード分析

序文: Vue3 がリリースされてからかなり経ちますが、最近、会社のプロジェクトでVue3 + Ty...

JSデータ型検出のさまざまな方法の概要

目次背景データ型を決定する方法は何ですか? 1. typeof を使用して基本データ型を決定します。...

Vue での親子コンポーネント通信と、sync を使用して親子コンポーネント データを同期する

目次序文子コンポーネントは親コンポーネントにデータを渡す1. 親コンポーネントから子コンポーネントに...

Linux サーバーでの MySQL インストール情報の表示

mysql のインストール情報を表示します。 #ps -ef | grep mysql usr/bi...

IdeaはリモートDockerをデプロイし、ファイルを構成する

1. LinuxサーバーのDocker構成ファイルを変更する vim /usr/lib/system...

WeChatミニプログラム開発のためのコンポーネント設計仕様

WeChat ミニプログラム コンポーネント設計仕様コンポーネントベースの開発という考え方は、私の開...

ARM64アーキテクチャでmysql5.7.22をインストールするプロセス全体

MySQLダウンロードアドレス: https://obs.cn-north-4.myhuaweicl...

Vueのフィルターについて知っておくべきこと

目次序文フィルターとは何かフィルターの使い方グローバルフィルターローカルフィルターフィルターは直列に...

Tomcat をアンインストールして再インストールする方法 (画像とテキスト付き)

tomcat9をアンインストールする1. Tomcatのインストールはディレクトリに解凍するだけで...

Dockerを使用してSonarQubeをインストールする詳細なチュートリアル

目次1. イメージをプルする1.1 関連するイメージをプルして実行する1.1.1 関連する画像を取得...

Linux 上でプロジェクトをリリースするために Tomcat を展開するプロセスにおけるさまざまな問題と解決策

プロジェクトをプロジェクトサイトのテスト環境にデプロイするJDK1.8トムキャット8.5 Maven...

11 の素晴らしい JavaScript コード リファクタリングのベスト プラクティスの概要

目次1. 関数の抽出2. 重複した条件付きスニペットを結合する3. 条件分岐文を関数に抽出する4. ...

MySQL でよく使用されるステートメントの包括的な概要 (必読)

以下にまとめたナレッジポイントはどれもよく使われる貴重な情報ばかりですので、ぜひ上手に集めてください...

Docker Compose で環境変数を参照する方法の例

プロジェクトでは、さまざまな条件や使用シナリオを制御するために、docker-compose.yml...