1. 対象となる効果
ソースコードは以下にありますので、コピーして貼り付けてください
(1) 先頭に合計線が配置され、文字色が太くなり、合計線の背景色も太くなります
(2) 合計行の年齢は平均値として計算され文字色は緑色、プロパティは合計として計算され文字色は赤色になります
2. 原則
2.1. el-table のshow-summary合計行はデフォルトで最後に配置されます。
次の CSS を追加するだけです:親セレクター /deep/ 子セレクター スタイルの浸透を実現します。
/* 合计行位置修改开始 */ .el-table { display: flex; flex-direction: column; } .el-table /deep/ .el-table__body-wrapper { order: 1; } /* 合计行位置修改结束*/
2.2. 合計行全体のスタイルを変更する
/* 合计行整体样式修改开始 */ .el-table /deep/ .el-table__footer-wrapper tbody td { background: black; color: white; font-weight: bolder; } /* 合计行整体样式修改结束*/
2.3. 要約メソッド: :summary-method="getSummaries"
// 合计行方法 getSummaries(param) { const { columns, data } = param; const sums = []; columns.forEach((column, index) => { if (column.property == 'date') { sums[index] = '总价'; return; } // values是每一列的数据是一个数组 const values = data.map(item => Number(item[column.property])); // 数字列才进行合计计算 if (!values.every(value => isNaN(value))) { // 对values进行一个累加操作,累加那些非NAN的值 const total = values.reduce((prev, curr) => { const value = Number(curr); if (!isNaN(value)) { return prev + curr; } else { return prev; } }, 0); // 年龄计算平均值 if (column.property == 'age') { sums[index] = total / data.length } // 财产计算总数 if (column.property == 'money') { sums[index] = total} } } }); // 将合计结果返回,是一个数组,每个位置的值与表格的列一一对应 return sums }
columns はオブジェクトの配列である各列の情報を表示します。
dataは各行の情報であり、行全体をカウントしないオブジェクト配列でもあります。
sums は合計行であり、 typescriptのタプルです。つまり、異なる型の要素を配列に格納できます。
2.4、合計行セルのスタイル
2.4.1、cssメソッド
.el-table /deep/ .el-table__footer-wrapper tbody td:nth-child(3) { color: lightgreen; font-weight: bolder; } .el-table /deep/ .el-table__footer-wrapper tbody td:nth-child(4) { color: red; font-weight: bolder; }
欠点: 各列の位置を手動で計算する必要があり、一度列の位置が変更されると、メンテナンスが容易ではありません。
2.4.2、jsx の方法
合計行で jsx を返し、VNode を生成し、スタイルを動的に生成します
// 年龄计算平均值(绿色) if (column.property == 'age') { sums[index] = <span class={'green'}>{total / data.length}</span> } // 财产计算总数(红色) if (column.property == 'money') { sums[index] = <span class={'red'}>{total}</span> }
.red { color: red; font-weight: bolder; } .green { color: lightgreen; font-weight: bolder; }
合計は VNode を返します
2.5. 合計行セルの結合
2.5.1、他の人のブログのやり方(エラーが報告されます)
watch: { 表格数据: { immediate: true, handler() { const tds = document.querySelectorAll('#table .el-table__footer-wrapper tr>td'); tds[0].colSpan = 2; tds[0].style.textAlign = 'center' tds[1].style.display = 'none' } } },
2.5.2、elementUI で行を結合する方法
:span-method には合計行数は含まれません
2.5.3. この記事の方法(推奨)
方法 1 に基づく変換:
watch: { tableData: { immediate: true, handler() { setTimeout(() => { const tds = document.querySelectorAll('#table .el-table__footer-wrapper tr>td'); tds[0].colSpan = 2; tds[0].style.textAlign = 'center' tds[1].style.display = 'none' }, 0) } } },
なぜこのようなことが可能なのでしょうか?
Vue では、テンプレートを使用して HTML を作成することをお勧めします。ただし、実際の DOM ノードではありません。Vue は最初にオブジェクト内のrender関数を使用して仮想 DOM ノードを生成し、それをマウントします。マウントされた実際の DOM は非同期でレンダリングされ、状態が変更された後も非同期でレンダリングされます。document.querySelectorAll操作はコード内で同期タスクとして定義されており、イベント キューは次のようになります。
同期キュー: dom要素を取得
非同期キュー: 仮想ノードから実ノードに変換してレンダリング同期→非同期の
実行プロセス によりセルのマージができないsetTimeout を使用して実行のために要素を非同期キューに配置し、ページがロードされた後に dom 要素を取得すると成功します。
2.6. 合計行には固定列があります
合計行に固定列がある場合、次の問題が発生します。
(1)固定列の合計行が下まで伸びました
(2)セル結合の効果が消える
次の CSS を追加し、いくつかの JS を変更します
/* 存在固定列时,合计行位置修改开始 */ .el-table /deep/ .el-table__fixed { display: flex; flex-direction: column; } .el-table /deep/ .el-table__fixed-footer-wrapper, .el-table /deep/ .el-table__fixed-body-wrapper, .el-table /deep/ .el-table__fixed-header-wrapper { position: initial; } .el-table /deep/ .el-table__fixed-body-wrapper { order: 1; } .el-table /deep/ .el-table__fixed-footer-wrapper tbody td.el-table__cell { border-top: none; background: black; color: white; font-weight: bolder; } /* 存在固定列时,合计行位置修改开始 */
最終的な効果は以下の通りです。
3. ソースコード
app.vue
<template>
<div id="app">
<SummaryTable></SummaryTable>
</div>
</template>
<script>
import SummaryTable from '@/components/SummaryTable'
export default {
components: {
SummaryTable
},
name: 'App',
data() {
return {
}
},
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
SummaryTable.vue
<template>
<div>
<el-table ref="table" id="table" :data="tableData" border style="width: 100%" show-summary
:summary-method="getSummaries">
<el-table-column prop="date" label="日期" width="180" fixed="left">
</el-table-column>
<el-table-column prop="name" label="姓名" width="180" fixed="left">
</el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="money" label="财产"></el-table-column>
<el-table-column prop="money" label="财产"></el-table-column>
<el-table-column prop="money" label="财产"></el-table-column>
<el-table-column prop="money" label="财产"></el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
tableData: [{
date: '2016-05-01',
name: '王小虎',
age: 13,
money: 100
}, {
date: '2016-05-02',
name: '王小虎',
age: 25,
money: 333
}, {
date: '2016-05-03',
name: '王小虎',
age: 33,
money: 555
}, {
date: '2016-05-04',
name: '王小虎',
age: 23,
money: 200
},
{
date: '2016-05-05',
name: '王小虎',
age: 26,
money: 666
}],
}
},
watch: {
tableData: {
immediate: true,
handler() {
setTimeout(() => {
const tds = document.querySelectorAll('#table .el-table__fixed-footer-wrapper tr>td');
tds[0].colSpan = 2;
tds[0].style.textAlign = 'center'
tds[1].style.display = 'none'
}, 0)
}
}
},
methods: {
// 合计行方法
getSummaries(param) {
const { columns, data } = param;
const sums = [];
columns.forEach((column, index) => {
if (column.property == 'date') {
sums[index] = '总价';
return;
}
// values是每一列的数据是一个数组
const values = data.map(item => Number(item[column.property]));
if (!values.every(value => isNaN(value))) {
// 对values进行一个累加操作,累加那些非NAN的值
const total = values.reduce((prev, curr) => {
const value = Number(curr);
if (!isNaN(value)) {
return prev + curr;
} else {
return prev;
}
}, 0);
// 年龄计算平均值(绿色)
if (column.property == 'age') {
sums[index] = <span class={'green'}>{total / data.length}</span>
}
// 财产计算总数(红色)
if (column.property == 'money') {
sums[index] = <span class={'red'}>{total}</span>
}
}
});
// 将合计结果返回,是一个数组,每个位置的值与表格的列一一对应
return sums
}
}
}
</script>
<style scoped>
.red {
color: red;
font-weight: bolder;
}
.green {
color: lightgreen;
font-weight: bolder;
}
/* 存在固定列时,合计行位置修改开始 */
.el-table /deep/ .el-table__fixed {
display: flex;
flex-direction: column;
}
.el-table /deep/ .el-table__fixed-footer-wrapper,
.el-table /deep/ .el-table__fixed-body-wrapper,
.el-table /deep/ .el-table__fixed-header-wrapper {
position: initial;
}
.el-table /deep/ .el-table__fixed-body-wrapper {
order: 1;
}
.el-table /deep/ .el-table__fixed-footer-wrapper tbody td.el-table__cell {
border-top: none;
background: black;
color: white;
font-weight: bolder;
}
/* 存在固定列时,合计行位置修改开始 */
/* 默认有1px去掉样式影响 */
.el-table /deep/ .el-table__fixed::before {
height: 0;
}
/* 合计行整体样式修改开始 */
.el-table /deep/ .el-table__footer-wrapper tbody td {
background: black;
color: white;
font-weight: bolder;
}
/* 合计行整体样式修改结束*/
/* 合计行位置修改开始 */
.el-table {
display: flex;
flex-direction: column;
}
.el-table /deep/ .el-table__body-wrapper {
order: 1;
}
/* 合计行位置修改结束*/
</style>