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 iframe で親ページと子ページ間の双方向メッセージングを実装する例

ある日、リーダーはメイン ページに iframe を埋め込み、親ページと子ページ間で双方向にメッセー...

CSSタグの表示モードの詳細な説明

ラベル表示モード(重要) divタグとspanタグ1. スタイルはまったく同じですが、ラベルが異なり...

json.stringify() と json.parse() の違いと使い方

1. JSON.stringify() と JSON.parse() の違い私たちは皆、JSON.s...

リンクAの意味論、書き方、ベストプラクティス

リンク A のセマンティクス、ライティング スタイル、およびベスト プラクティス。私は JavaEy...

MySQLの暗黙的な変換問題の解決

1. 問題の説明 root@mysqldb 22:12: [xucl]> テーブル t1\G ...

複数クリックを防ぐVueの実践

通常、クリック イベントは、メッセージ リマインダーのさまざまな状況に分割されます。これらが処理され...

Bash で山括弧を使用するその他の方法

序文この記事では、山括弧のその他の用途をさらに詳しく見ていきます。前回の記事では、山括弧 (<...

シンプルなアコーディオン効果を実現するjs

この記事では、アコーディオン効果を実現するためのjsの具体的なコードを参考までに共有します。具体的な...

Tkinterはjsキャンバスを使用してグラデーションカラーを実現します

目次1. RGBを使用して色を表す2. Tkinter キャンバスコンポーネント3. グラデーション...

優れたウェブフロントエンドデザインの指標

Web ページのアクセシビリティは、フロントエンドでのみ評価および実装できるもののようです。ユーザビ...

アイデアを war パッケージにパッケージ化し、tomcat にデプロイしてアクセス パスの問題 (図とテキスト)

Web プロジェクトを war にパッケージ化するアイデアにとって最も重要なことは、アトリフィカを...

携帯電話向けウェブページ作成のヒント

現在では多くの人がスマートフォンを使用していることを考慮すると、モバイル Web ページの書き方は、...

Ubuntu 20.04でLNMP環境を構築する方法

簡単な説明以前 Centos7 で構築し、その後個人開発環境として Ubuntu 20.04 を使っ...

JavaScript setinterval 1秒遅延ソリューション

setinterval を使用すると、ページを開いた直後に 1 秒の遅延後に実行されることがわかりま...

MySQL 8.0 の新機能の分析 - トランザクション データ ディクショナリとアトミック DDL

序文トランザクション データ ディクショナリとアトミック DDL は、MySQL 8.0 で導入され...