PS:もし自分を一時的に律することができないなら、自分を忙しくさせることを考えましょう。
前の数記事ではインターフェース開発、Thymeleaf テンプレートおよびその一般的な構文を試しました。この記事を読む前に、前の数記事を読むことができます:
- Spring Boot シリーズのインターフェースを開発する
- Spring Boot シリーズの Thymeleaf テンプレート入門
- Spring Boot シリーズの Thymeleaf 一般的な構文
Thymeleaf テンプレートのレイアウトは、主にフロントエンドページをより良く分割するために、Thymeleaf に関連する構文を使用してフロントエンドページのレイアウトを行います。主な内容は以下の通りです:
- テンプレートフラグメントの引用
- フラグメント式の構文
- パラメータ化されたテンプレートフラグメント
- テンプレートフラグメントの削除
- テンプレートレイアウトの継承
テンプレートフラグメントの引用#
th:fragment
を使用して、他のページが引用できるレイアウトフラグメントを定義できます。foter.html でのテンプレートフラグメントの定義は以下の通りです:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Footer</title>
</head>
<body>
<!--レイアウトフラグメントの定義-->
<div th:fragment="copy">
© 2020 躬行之
</div>
</body>
</html>
上記では、copy という名前のフラグメントを定義しました。th:insert
、th:replace
、およびth:include
を使用してテンプレートフラグメントを挿入できます。その中で、th:include
は Thymeleaf 3.0 以降は推奨されなくなりました。home.html でテンプレートフラグメントを引き入れる方法は以下の通りです:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Template Layout.</title>
</head>
<body>
<!--テンプレートフラグメントの引き入れ-->
<div th:insert="~{footer::copy}"></div>
</body>
</html>
プロジェクトを実行し、http://localhost:8080/home
を確認すると、以下のようになります:
© 2020 躬行之
© 2020 躬行之
次に、th:insert
、th:replace
、およびth:include
の 3 つの違いを見てみましょう。copy
という名前のテンプレートフラグメントをそれぞれの方法で引き入れる方法は以下の通りです:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Template Layout.</title>
</head>
<body>
<!--th:insert、th:replace、th:includeの違い-->
<p>---th:insert、th:replace、th:includeの違い---</p>
<!--テンプレートフラグメントを直接挿入-->
<div id="insert" th:insert="~{footer::copy}">insert</div>
<!--現在のフラグメントを直接置き換え-->
<div id="replace" th:replace="~{footer::copy}">replace</div>
<!--指定されたフラグメントの内容を現在のフラグメントに直接挿入-->
<div id="include" th:include="~{footer::copy}">include</div>
</body>
</html>
上記のコードでは、3 つのdiv
がそれぞれid
をinsert
、replace
、include
に設定しています。プロジェクトを実行した後、ブラウザでソースコードを確認すると、以下のようになります:
<!--...-->
<!--th:insert、th:replace、th:includeの違い-->
<p>---th:insert、th:replace、th:includeの違い---</p>
<div id="insert">
<div>
© 2020 躬行之
</div>
</div>
<div>
© 2020 躬行之
</div>
<div id="include">
© 2020 躬行之
</div>
<!--...-->
3 者の違いは以下の通りです:
th:insert
:テンプレートフラグメントを直接挿入;th:replace
:現在のフラグメントを直接置き換え;th:include
:指定されたフラグメントの内容を現在のフラグメントに直接挿入。
フラグメント式の構文#
テンプレートは主にフラグメント式を使用しています。フラグメント式の構文は以下の通りです:
〜{templatename::selector}
: 指定されたテンプレートの指定されたフラグメント名のテンプレートフラグメントを引き入れる;〜{templatename}
: 指定されたテンプレートのすべてのフラグメントを引き入れる;〜{:: selector}
: 同じく〜{this:: selector}
、現在のテンプレートの指定された名前のテンプレートフラグメントを引き入れる。
ここで、templatename
はテンプレート名を示し、上記の文中のfooter
、selector
はフラグメント名を示し、上記の文中のcopy
です。
さらに、selector
は ID セレクタ、クラスセレクタ、タグでもあり、th:fragment
を定義していない場合でも関連するテンプレートフラグメントを使用できます。以下のように:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Footer</title>
</head>
<body>
<div id="head">
<p>th:fragmentを定義していない場合のフラグメント式の使用--id</p>
</div>
<div class="head">
<p>th:fragmentを定義していない場合のフラグメント式の使用--class</p>
</div>
<div>
<span>th:fragmentを定義していない場合のフラグメント式の使用--span</span>
</div>
</body>
</html>
別のテンプレートで上記のコードフラグメントを使用できます。以下のように:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Template Layout.</title>
</head>
<body>
<!--th:fragmentを定義していない場合のフラグメント式の使用-->
<div th:insert="~{footer::#head}"></div>
<div th:insert="~{footer::.head}"></div>
<div th:insert="~{footer::span}"></div>
</body>
</html>
プロジェクトを実行すると、結果は以下の通りです:
th:fragmentを定義していない場合のフラグメント式の使用--id
th:fragmentを定義していない場合のフラグメント式の使用--class
th:fragmentを定義していない場合のフラグメント式の使用--span
パラメータ化されたテンプレートフラグメント#
th:fragment
を使用してテンプレートフラグメントを定義する際に、パラメータを追加できます。以下のように:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Footer</title>
</head>
<body>
<!--テンプレートフラグメントにパラメータを追加-->
<div th:fragment="frag(name)" th:assert="${!#strings.isEmpty(name)}">
<p th:text="公众号名称+':'+${name}">Default</p>
</div>
</body>
</html>
次に、対応するページで上記のフラグメントを引用し、対応するパラメータを渡すことができます。以下のように:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Template Layout.</title>
</head>
<body>
<!--パラメータ化されたテンプレートフラグメント-->
<div th:insert="~{footer::frag(${gzh})}"></div>
<!--この書き方では、複数のパラメータがある場合、順序を変更できます-->
<div th:insert="~{footer::frag(name=${gzh})}"></div>
</body>
</html>
上記のコードでパラメータ値gzh=躬行之
を使用し、プロジェクトを実行すると、結果は以下の通りです:
公众号名称:躬行之
公众号名称:躬行之
ここで、テンプレートフラグメント内でth:assert
属性を使用してパラメータの検証を行うことができ、th:assert
内の式の値がすべてtrue
である場合のみ続行され、それ以外の場合は例外がスローされます。
テンプレートフラグメントの削除#
テンプレートフラグメントを削除するには、th:remove
属性を使用します。この属性に設定できる値は以下の通りです:
- all: 所在のタグとすべての子タグを削除;
- body: 所在のタグを削除せず、対応する子タグのみを削除;
- tag: 所在のタグのみを削除し、その子タグは削除しない;
- all-but-first: 所在のタグの最初のものを除くすべての子タグを削除;
- none : 何の削除操作も行わない。
具体的な使用方法は以下の通りです:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
<tr>
<th>NAME</th>
<th>PRICE</th>
<th>COMMENT</th>
</tr>
<!--所在のタグとすべての子タグを削除-->
<tr th:remove="all">
<td>A</td>
<td>1</td>
<td>AA</td>
</tr>
<!--所在のタグを削除せず、対応する子タグのみを削除-->
<tr th:remove="body">
<td>B</td>
<td>2</td>
<td>BB</td>
</tr>
<!--所在のタグのみを削除し、その子タグは削除しない-->
<tr th:remove="tag">
<td>C</td>
<td>3</td>
<td>CC</td>
</tr>
<!--所在のタグの最初のものを除くすべての子タグを削除-->
<tr th:remove="all-but-first">
<td>D</td>
<td>4</td>
<td>DD</td>
</tr>
<!--何の削除操作も行わない-->
<tr th:remove="none">
<td>E</td>
<td>5</td>
<td>EE</td>
</tr>
</table>
</body>
</html>
主にth:remove
属性に設定された異なる値を実行した後の効果に注目し、次のようなページになります:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table>
<tr>
<th>NAME</th>
<th>PRICE</th>
<th>COMMENT</th>
</tr>
<!--所在のタグとすべての子タグを削除-->
<!--所在のタグを削除せず、対応する子タグのみを削除-->
<tr></tr>
<!--所在のタグのみを削除し、その子タグは削除しない-->
<td>C</td>
<td>3</td>
<td>CC</td>
<!--所在のタグの最初のものを除くすべての子タグを削除-->
<tr>
<td>D</td>
</tr>
<!--何の削除操作も行わない-->
<tr>
<td>E</td>
<td>5</td>
<td>EE</td>
</tr>
</table>
</body>
</html>
テンプレートレイアウトの継承#
テンプレートレイアウトの継承には、th:fragment
とth:replace
を使用します。以下の例を通じて、テンプレートレイアウトの継承の書き方を示します。継承するページを以下のように定義します:
<!DOCTYPE html>
<html th:fragment="layout (title, content)" xmlns:th="http://www.thymeleaf.org">
<head>
<title th:replace="${title}">Layout Title</title>
</head>
<body>
<h1>Layout H1</h1>
<div th:replace="${content}">
<p>Layout content</p>
</div>
<footer>
Layout footer
</footer>
</body>
</html>
上記のページを継承するファイルは、上記のtitle
とcontent
の値を置き換えます。上記のページを継承する書き方は以下の通りです:
<!DOCTYPE html>
<html th:replace="~{base :: layout(~{::title}, ~{::section})}" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Page Title</title>
</head>
<body>
<section>
<p>Page content</p>
<div>Included on page</div>
</section>
</body>
</html>
実行後の効果は以下の通りです:
Layout H1
Page content
Included on page
Layout footer