前回はこちら。
html-css-javascript.hatenadiary.com
さて、候補者追加や投票の機能は完成しました。
なのですが、実際にやってみるとわかるのですが、投票をしてそれが反映されるまでに時間がかかります。
というわけでこの辺を修正していこうと思います。
反映までの時間がかかる原因と対策
これは明らかに以下が原因ですね。
.then((data) => { console.log(data.message); location.reload(); })
投票するごとにサーバーからデータを受け取ってページを全部読み込んで、再描画しています。
そりゃあ時間もかかります。
そんなことをせず、投票数だけ1増やせばいいんです。
そうすれば全部読み込んだり再描画する必要はなくなります。
というわけでlocation.reload()は削除一択です。
さらに同じことが候補追加のときも言えます。
候補を追加するだけなんですから、すべてを読み込んで描画するのではなく、候補追加のところだけ変更すればいいわけです。
ではどうするのかというと、GETで取得したところをすべて関数にしてしまいます。
それをリロードのところで呼び出すと、サーバーでの最新情報を描画することになります。
まずはGETを関数化。
function loadCandidates() { fetch("http://localhost:3000/api/candidates") .then((response) => { if (!response.ok) { throw new Error("HTTPエラー"); } return response.json(); }) .then((data) => { console.log("取得したデータ:", data); candidates = data; candidateList.innerHTML = ""; // 念のためクリア render(); }) .catch((err) => { console.error(err); showError(); }
showError();はエラーのときの処理です。
あとから定義します。
で、これを3か所で呼び出します。
location.reload();があったところです。
①定義したところ
まず一番最初にサーバーの最新状態を表示する必要があります。
なので定義した直後に呼び出す必要があります。
このとき、普通に呼び出してもいいのですが、タイミングを安定させるためにHTMLの読み込みを終了した後という風に書きます。
window.addEventListener("DOMContentLoaded", () => { loadCandidates(); });
DOMContenLoadedはclickとかsubmitと同じようなイベントで、HTMLの読み込みと解析が終わって、画面の部品(DOM)が全部使えるようになったタイミングで発生します。
で、そのタイミングでイベントが発火しますので、loadCandidates()が呼び出されます。
②クリックイベントのところ
.then((response) => response.json()) .then((data) => { console.log(data.message); //location.reload();
③サブミットイベントのところ
.then((response) => response.json()) .then((data) => { console.log(data.message); inputName.value = ""; inputAge.value = ""; //location.reload(); ここ loadCandidates(); // 候補者リストを再読み込み }) .catch((err) => { console.error(err); });
.catch((err) => { console.error(err); });
この部分が被ってるように見えますが、loadCandidatesの中の方はGETに関するもので、その外の部分はPOSTに関するものなのでこの書き方で問題はありません。
これでページ全体をリロードするのではなく、renderの中身に定義されているようにDOM操作で要素のみを追加しているだけなので軽くなります。
実行・・・。
ちゃんと軽くなりました。
リロードボタン
そうすると、再読み込みをするボタンが欲しくなります。
このボタンも作っておきましょう。
HTMLに以下を追加します。
<button id="reloadBtn">再読み込み</button>
で、Script.jsに以下を追加します。
const reloadBtn = document.getElementById("reloadBtn"); if (reloadBtn) { reloadBtn.addEventListener("click", () => { loadCandidates(); }); }
この辺はあっさりしたもんです。
VSCodeを使ってたら一瞬でできますね。
削除ボタン
管理人画面においては候補者の削除ボタンも必要になりますね。
JavaScriptのrenderでチェックボックスという新しい要素を追加するようにして、そこでチェックをできるようにして、削除ボタンを押したらfetchでバックエンドへチェックボックスの操作を処理するPOSTリクエストを送信、バックエンドで保存とフロントでの表示をするためにGETリクエストを受けてフロントで表示の処理、といった感じですね。
いっきに書いてしまいましたが、ちょっと長くなりそうなので次回に回します。