教材の内容に関係のない質問や教材とは異なる環境・バージョンで進めている場合のエラーなど、教材に関係しない質問は推奨していないため回答できない場合がございます。
その場合、teratailなどの外部サイトを利用して質問することをおすすめします。教材の誤字脱字や追記・改善の要望は「文章の間違いや改善点の指摘」からお願いします。
カリキュラム2-9
から、
という2段階の対応の内、1の対応を進めてきました。
前パートで1の対応は完了したので、カリキュラム2-12
~2-15
にかけては、2番目の「前のページへ」「次のページへ」リンクを正式な形で実装する対応を行っていきます。
views/blog.ejs
のテンプレート出力処理内から現在のページ番号を参照できるようにする本パート終了時には以下のような状態になります。
npm start
でサーバーアプリケーションを起動させてください。まず、「前のページへ」「次のページへ」リンク作成に必要な情報である「現在のページ番号」をviews/blog.ejs
のテンプレート出力処理に渡すように/blog/
ルーティング処理を変更します。
VSCodeのファイル一覧からserver.js
を選択して、エディタで表示させてください。
そして、/blog/
ルーティング処理のコードを以下のように変更してください。
server.js12345678910111213141516 -++ Copied!app.get('/blog/', (request, response) => {
// ========== 中略 ==========
// ページに応じた記事一覧に絞る(1ページ5件)
const startIndex = (request.query.page - 1) * 5;
const endIndex = startIndex + 5;
const displayEntries = entries.slice(startIndex, endIndex);
// テンプレートを使用して出力したHTMLをクライアントに送信
response.render('blog', {
entries: displayEntries,
sideList
sideList,
currentPage: request.query.page
});
});
上記変更部分のsideList
の行は単純に末尾にカンマを追加しただけなので、処理の動きを変更するものではありません。
実質的な変更部分は、views/blog.ejs
のテンプレート出力処理にcurrentPage
というプロパティを渡す部分になります。
currentPage
の内容はrequest.query.page
となっています。これは前パートで確認した、URLパラメータである?page=x
のx
です。
この変更により、views/blog.ejs
のテンプレート出力処理内からcurrentPage
という変数名で現在のページ番号を参照できるようになりました。
次に、views/blog.ejs
のテンプレート出力処理の変更を行います。
VSCodeのファイル一覧からviews/blog.ejs
を選択して、エディタで表示させてください。
そして、<div class="page-links">
タグ内(前パートで仮の「次のページへ」リンクを追加した部分)のコードを以下のように変更してください。
views/blog.ejs123456789101112 -++ Copied!<div class="main-content">
<h1><a href="/blog/">担当者Aのブログ</a></h1>
<article>
<!---------- 中略 ---------->
</article>
<div class="page-links">
<a href="?page=3">次のページへ</a>
<a href="?page=<%= currentPage - 1 %>">前のページへ</a>
<a href="?page=<%= currentPage + 1 %>">次のページへ</a>
</div>
</div>
前パートで設置した仮の「次のページへ」リンクを消し、正式な「前のページへ」「次のページへ」リンクを設置しています。
「前のページへ」リンクの内容について解説します。
diff1+Copied! <a href="?page=<%= currentPage - 1 %>">前のページへ</a>
href
のリンク先指定の中で<%= ~ %>
というタグが使用されています。
カリキュラム2-3
で触れましたが、<%
の後に=
が付いている場合は、タグ内の変数もしくは処理結果をそのまま文字列として出力するという指定になります。
この<%= ~ %>
の中で、先ほど/blog/
ルーティング処理で新たに追加したcurrentPage
を参照しています。
?page=3
というURLパラメータが指定されている場合は、このcurrentPage
に3
が入ってくることになります。
この行は「前のページへ」リンクなので、現在のページ番号の1つ前であるcurrentPage - 1
という指定になっています。
したがって、現在のページ番号が3
の場合、HTMLとして出力される上記リンクのhref
は?page=2
となります。
「次のページへ」リンクもほぼ同様の内容です。
diff1+Copied! <a href="?page=<%= currentPage + 1 %>">次のページへ</a>
「前のページへ」リンクがcurrentPage - 1
だったのに対し、「次のページへ」リンクではcurrentPage + 1
という指定になっています。
つまり、現在のページ番号が3
の場合、HTMLとして出力される上記リンクのhref
は?page=4
となります。
これでテンプレート側の修正も完了したので、ブラウザで出力内容を確認してみましょう。
ブラウザのアドレスバーにhttp://127.0.0.1:15864/blog/?page=3
と入力してエンターを押してください。
記事一覧ページが表示されます。
また、一番下までスクロールすると「前のページへ」「次のページへ」リンクが追加されているのが確認できます。
それぞれのリンク先URLを確認してみましょう。
まず、「前のページへ」リンクです。「前のページへ」リンクにマウスカーソルを合わせるとブラウザの左下にリンク先のURLが表示されます。
想定通りhttp://127.0.0.1:15864/blog/?page=2
というURLになっています。
次に「次のページへ」リンクを見てみましょう。同じように「次のページへ」リンクにマウスカーソルを合わせてください。
???こちらは想定外の内容となっています。
想定ではhttp://127.0.0.1:15864/blog/?page=4
となるはずが、http://127.0.0.1:15864/blog/?page=31
となっています。
31
という数字はどこから出てきたのでしょう。
実は、これは31
(さんじゅういち)という数値ではなく、'31'
(さんいち)という文字列になってしまっているのです。
カリキュラム2-10
で確認したrequest.query
の内容を思い出してみましょう。
request.query
の内容は{ page: '3' }
となっていました。
3
がシングルクォーテーションで囲まれているということは、この3
は文字列であるということです。
URLに付加されたパラメータはすべて文字列としてrequery.query
に登録されます。
/blog/
ルーティング処理では、このrequest.query
に登録されたpage
プロパティをそのままcurrentPage
としてviews/blog.ejs
のテンプレート出力処理に渡しています。
つまり、views/blog.ejs
のテンプレート出力処理内のcurrentPage
は3
という数値ではなく、'3'
という文字列であるということです。
先ほど追加した「次のページへ」リンクの設定は以下のようになっています。
html1 Copied!<a href="?page=<%= currentPage + 1 %>">次のページへ</a>
したがって、currentPage + 1
というのは、'3' + 1
という計算と同義ということです。
JavaScriptにおいての+
演算子には、数値の加算の他に文字列の連結という働きがあります。
そして、+
の左辺右辺どちらかが文字列の場合は、文字列の連結として動作します(1
が'1'
という文字列として扱われる)。
currentPage
の'3'
は数字ではあっても型としては数値ではなく文字列なので、'3' + '1' = '31'
という結果になってしまったのです。
では、なぜ「前のページへ」リンクは大丈夫だったのでしょうか。
+
と違い、-
には文字列を操作する挙動は存在しないので、-
が指定された時点で数値の減算として実行されます。
そのおかげで、'3' - 1
は3 - 1 = 2
として動作したということです。
ただ、これはそういう仕様に恵まれてたまたま正常に動作しただけの話なので、加算・減算をする値ということであれば、根本的にはcurrentPage
の型は数値であるべきです。
次のパートでは、currentPage
の型を数値に変更し、「次のページへ」リンクのURLが想定通りの内容になるように修正していきます。
本パートは以上になります。
お疲れ様でした。