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 ロケーション設定(ロケーションのマッチング順序)の詳細な説明

推薦する

MySQL におけるデフォルトの使用法の詳細な説明

NULL および NOT NULL 修飾子、DEFAULT 修飾子、AUTO_INCREMENT 修...

MySQL InnoDB row_id 境界オーバーフロー検証方法の手順

背景クラスメートと row_id の境界問題について話し合ったので、ここで詳しく説明します。 Inn...

Linux でスレッドを作成するための pthread_create の具体的な使用法

pthread_create関数機能紹介pthread_createはUNIX環境のスレッド作成関数...

Zabbixで指定時間内の変化値を設定する方法の詳細な説明

背景説明: 既存の負荷分散装置には、付加価値状態にある指標があります (増加するだけで減少しないため...

意外と知らないJSのループ速度テストのいろいろを徹底解説

目次序文1. forループ2. whileループとdo-whileループ3. forEach、map...

HTML入力ファイルコントロールはアップロードされるファイルの種類を制限します

入力ファイルの HTML コントロールを Web ページに追加します。 <input id=&...

JSはタイムラインの自動再生を実現する

最近、次のような効果を実装しました。再生ボタンをクリックするとタイムラインの再生が開始され、一時停止...

高可用性 Web クラスターを実装するための Keepalived+Nginx+Tomcat サンプル コード

高可用性 Web クラスターを実現する Keepalived+Nginx+Tomcat 1. Ngi...

Vue プロジェクトにインターフェース リスニング マスクを追加する方法

1. 事業背景マスク レイヤーを使用してユーザーの異常な操作を遮断する方法は、フロントエンドでよく使...

MySQLが大量のデータを処理する際にクエリ速度を最適化するいくつかの方法

実際に参加したプロジェクトでは、MySQL テーブルのデータ量が数百万に達すると、通常の SQL ク...

nginxアクセス制御の実装例

高性能で軽量なウェブサービスソフトウェアであるNginxについて高い安定性 システムリソースの消費量...

Apache の一般的な仮想ホスト設定方法の分析

1. Apacheサーバーのインストールと設定yum インストール httpd -y systemc...

MySQL 5.7.21 解凍版のインストールと設定方法のグラフィックチュートリアル

私は頻繁にシステムをインストールするので、インストールのたびにいくつかのソフトウェアを再インストール...

mysql-joinsの具体的な使用方法

目次結合構文: 1. InnerJOIN: (内部結合) 2. LeftJOIN: (左結合) 3....

MySQLからOracleへのリアルタイム同期ソリューションの詳細な説明

1 要件の概要MySQL5.6本番データベースの複数のテーブルのデータは、Oracle11gデータウ...