HTML table要素の描画速度改善(ASP.NET MVC) -開発備忘録4-
こんばんは。桑山千雪は年下です。
今回は、ASP.NET MVCでweb画面上にtableを描画する際、描画速度がかなり重くなる書き方をしてしまっていたので、その改善策について記載します。
前提
用語について下記記載します。
ASP.NET MVCとは
過去記事で触れているので興味があれば参考にしてください
HTML table要素とは
HTMLとは、webページを作成するためのプログラミング言語です。
tableは、そのHTMLで使う記法の一つです。
tableを使うと下記のように、グルメ四天王のフルコースを表形式で表示できます。
困ったこと - データが多い時に描画が遅い
tableを使ってデータを表示する際、10件、20件であれば描画速度は全く気になりませんが、例えば1万件以上となると無視できなくなってきます。
描画速度は環境にもよりますが、筆者の場合、下記のようなhtmlを作成した結果1万件のデータを完全に描画するまでに40秒ほどかかりました。
<div style="text-align:center; margin-top:100px">
<table border="1">
<thead>
//表の列を作成
</thead>
<tbody>
@for (var i = 0; i < Model.FullCourseList.Count(); i++)
{
@using(Html.BeginForm("Action", "Controller", FormMethod.POST))
{
<tr>
<th id="PersonName(@i)">@Model.FullCourseList[i].PersonName</th>
<td id="Appetizer(@i)">@Model.FullCourseList[i].Appetizer</td>
<td id="Soup(@i)">@Model.FullCourseList[i].Soup</td>
<td id="FishDish(@i)">@Model.FullCourseList[i].FishDish</td>
<td id="MeatDish(@i)">@Model.FullCourseList[i].MeatDish</td>
<td id="MainDish(@i)">@Model.FullCourseList[i].MainDish</td>
<td id="Salad(@i)">@Model.FullCourseList[i].Salad</td>
<td id="Dessert(@i)">@Model.FullCourseList[i].Dessert</td>
<td id="Drink(@i)">@Model.FullCourseList[i].Drink</td>
<td><input id="Button(@i)" type="submit" value="選択"/></td>
@Html.Hidden("Name", "@Model.FullCourseList[i].PersonNameS")
</tr>
}
}
</tbody>
</table>
</div>
tbody内に実際のデータをループ処理で描画しています。
また、「選択」ボタンを押した際にボタンが配置されている行のデータをサーバに送るよう、一行ごとにフォームを記載しています。("@using(Html.BeginForm ~ " の箇所)
原因 - 一行ずつのフォームの描画に時間がかかる
tableの描画速度が遅い原因は、ループ処理で一行ごとにサーバ送信用のフォームを書いていることでした。
考えてみれば、全ての行にフォームを追加したとて、当然ながらボタン押下時にサーバにポストするフォームは一つだけなので、9999回分余計な描画をしてしまっていました。
対応 - 選択行のデータを送信するformを一つにする
対応としては、9999回分の無駄なフォーム描画をなくし、一つのみにすればいいので、table要素の外に一つのみフォームを記載しました。
ボタン押下時に呼び出したfunctionに行番号を渡すことで、何行目のデータを渡すのかを特定できるようにしています。
<div style="text-align:center; margin-top:100px">
<table border="1">
<thead>
//表の列を作成
</thead>
<tbody>
@for (var i = 0; i < Model.FullCourseList.Count(); i++)
{
<tr>
<th id="PersonName(@i)">@Model.FullCourseList[i].PersonName</th>
<td id="Appetizer(@i)">@Model.FullCourseList[i].Appetizer</td>
<td id="Soup(@i)">@Model.FullCourseList[i].Soup</td>
<td id="FishDish(@i)">@Model.FullCourseList[i].FishDish</td>
<td id="MeatDish(@i)">@Model.FullCourseList[i].MeatDish</td>
<td id="MainDish(@i)">@Model.FullCourseList[i].MainDish</td>
<td id="Salad(@i)">@Model.FullCourseList[i].Salad</td>
<td id="Dessert(@i)">@Model.FullCourseList[i].Dessert</td>
<td id="Drink(@i)">@Model.FullCourseList[i].Drink</td>
<td><input id="Button(@i)" type="button" value="選択" onclick="SelectButtonClick(@i)"/></td>
</tr>
}
</tbody>
</table>
@using(Html.BeginForm("Action", "Controller", FormMethod.POST, new { id = "PostForm" }))
{
@Html.Hidden("Name", "@Model.FullCourseList[i].PersonNameS", new { id = "PostName" })
}
</div>
<script>
function SelectButtonClick (index){
document.getElementById("PostName").value = document.getElementById("PersonName(" + index + ")").innerHTML;
document.forms['PostForm'].submit();
}
</script>
上記に修正した結果、1万件のデータ描画時間を40秒→10秒に短縮することができました。
これ以上の短縮は、そもそも表を何ページかに分けて1ページ分のみ描画するとかしないと無理ですが、ページネーションするにしても上記の対応は有効です。
結び
tableの描画速度には、今回記載した内容以外も要因として絡むので、その時その時で適切な修正をしていきたいです。
この記事が気に入ったらサポートをしてみませんか?