在开发Web网站的时候,HTML页面有很多是相同的,如果每一个页面都写一遍,不仅非常麻烦,而且非常不利于后期的更改。典型的如导航栏、页脚等,每个HTML页面几乎都一样。
在Thymeleaf中我们通过如下的机制来抽取处公共的页面,并在需要的时候引入这个页面就可以了。
建立一个公共页面,存放公共代码块
使用th:fragment
定义一个公共代码段。如下定义了两个公共代码段th:fragment="head(title)"
(title为引用公共代码段时传入的参数);th:fragment="menu(n)"
(n为引用代码段时传入的参数)。
<!DOCTYPE html>
<html lang="en" xmlns:th="">
<head th:fragment="head(title)"><!--title为传参-->
<meta charset="UTF-8">
<title th:replace="${title}">Home</title>
<link rel="stylesheet" href="../../static/bootstrap/css/" th:href="@{/bootstrap/css/}">
<script src="../../static/jquery/jquery-3.5." th:src="@{/jquery/jquery-3.5.}"></script>
<script src="../../static/bootstrap/js/" th:src="@{/bootstrap/js/}"></script>
<style>
body {
background: url(/images/)
no-repeat center center fixed;
background-size: cover;
}
</style>
</head>
<body>
<nav th:fragment="menu(n)" class="navbar navbar-inverse" style="font-size: 18px; background: rgba(0,0,0,0.75);">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="glyphicon glyphicon-align-justify" ></span>
</button>
<a class="navbar-brand" href="/index">EXCELLENT BLOG</a>
</div>
<div class="collapse navbar-collapse" >
<ul class="nav navbar-nav">
<li class="text-center" th:classappend="${n==1}?'active'"><a href="/index">首页</a></li>
<li class="text-center" th:classappend="${n==2}?'active'"><a href="#">说说</a></li>
<li class="text-center" th:classappend="${n==3}?'active'"><a href="#">博客</a></li>
<li class="text-center" th:classappend="${n==4}?'active'"><a href="#">社区</a></li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
其它<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li><a href="#">相册</a></li>
<li><a href="#">博客分类</a></li>
<li><a href="#">网站地图</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">留言板</a></li>
</ul>
</li>
<li>
<form class="navbar-form form-group">
<input class="form-control" type="text" placeholder="Search">
<input class=" btn btn-default" type="submit" value="搜索">
</form>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li th:classappend="${n==6}?'active'">
<a href="#" th:href="${==null}?'/login':'#'">
<span class="text-center" th:text="${==null}?'登录':${}">
uokaa
</span>
</a>
</li>
<li>
<a href="/logout">
<span class="text-center" th:text="${==null}?'':'注销'">
退出登录
</span>
</a>
</li>
</ul>
</div>
</nav>
</body>
</html>
<script>
$('.dropdown-toggle').dropdown();
</script>
在其他HTML文件中引用公共代码块
如在中引用公共代码段:
<!DOCTYPE html>
<html lang="en" xmlns:th="">
<head th:replace="common/header :: head(~{::title})">
<title>Home</title>
</head>
<body>
<nav th:replace="common/header :: menu(1)"></nav>
<div class="container-fluid">
<br><br><br><br><br>
<div class="row">
<div class="col-sm-6 col-sm-offset-3"><h1 class="text-center" style="color: white; font-size: 100px;"> W E L C O M E </h1></div>
</div>
</div>
</body>
</html>
1.<head th:replace="common/header :: head(~{::title})">表示用common/中的公共代码段"head"替换这里的<head>.
在替换的时候还可以传递参数,head(~{::title})表示引用下面的<title>中的值作为参数传递到公共代码段中(这种语法看着很不常见)。
2.<nav th:replace="common/header :: menu(1)"></nav>表示用common/中公的公共代码段"menu"替换这里的<nav>.
在替换的时候还可以传递参数,menu(1)表示将1作为参数传递到公共代码段中,公共代码短拿到参数后根据不同的值执行对应的操作,使得大部分代码一样,只有一小部分内容需要做相应的修改。
Thymeleaf标签定义:
th:fragment | 布局标签,定义一个代码片段,方便其它地方引用 | <div th:fragment="alert"> |
th:include | 保留自己的主标签,不保留th:fragment的主标签 | <div th:include="footer :: copy"></div> |
th:replace | 不保留自己的主标签,保留th:fragment的主标签 | <div th:replace="footer :: copy"></div> |
h:insert | 保留自己的主标签,保留th:fragment的主标签 | <div th:insert="header :: title"></div> |
其中:th:include="layout :: htmlhead" 中,layout为页面文件名,htmlhead为该文件中 th:fragment的值。
th:replace 、th:insert 同上。
示例:
公共页面代码(子页面):
<!DOCTYPE html>
<html xmlns:th="" lang="en">
<body>
<!-- th:fragment 定义用于加载的块 -->
<span th:fragment="footer">
it is test!
</span>
</body>
</html>
页面代码:
<!-- 保留自己的主标签,保留th:fragment的主标签。 -->
<div th:insert="test :: footer"></div>
<!-- 加载模板的内容: 读取加载节点的内容(不含节点名称),替换<div>的里面内容 -->
<div th:include="test::footer">test</div>
<!-- 替换当前标签为模板中的标签: 加载的节点会整个替换掉加载当前的<div> -->
<div th:replace="test::footer">test</div>
编译后:
<!-- 保留自己的主标签,保留th:fragment的主标签。 -->
<div><span>it is test!</span></div><!-- 加载模板的内容: 读取加载节点的内容(不含节点名称),替换<div>的里面内容 -->
<div> it is test!</div>
<!-- 替换当前标签为模板中的标签: 加载的节点会整个替换掉加载当前的<div> -->
<span>it is test!</span>