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の描画速度には、今回記載した内容以外も要因として絡むので、その時その時で適切な修正をしていきたいです。


この記事が気に入ったらサポートをしてみませんか?