恩
官方文档地址
让我们简短的分析下包含语句:
<div th:replace="fragments/header :: header">...</div>fragments/header 即为 fragments/header.html是我们正在引用的模板文件的名称,双冒号后面的表达式header是一个 fragment 选择器 。
文件 :fragments/header.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> ... </head> <body> <!--在这里指定 fragment --> <div th:fragment="header1"> <p>我是header1</p> </div> ... <div th:fragment="header2"> <p>我是header2</p> </div> </body>然后在其他HTML中:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <head> ... </head> <body> ... <!--引用 th:fragment="header1"--> <div th:replace="fragments/header :: header1">...<div> </body>就把第一个 div 引用过来了,通过这种方式,我们可以在一个模板文件中定义多个片段,就像上面做的那样。
这里重要的是,所有的模板仍然可以是自然模板,并且可以在没有运行服务器的浏览器中查看。
通过使用标记选择器语法,类似 jQuery 选择器,thymeleaf 可以选择任意部分作为片段,而不用事先标记。 标记选择器语法地址
<div th:insert="https://www.thymeleaf.org :: div.description" >...</div>上面的代码将包含一个来自thymeleaf.org 的 class=“description” 的 div 。
为了实现这一点,模板引擎必须配置为 UrlTemplateResolver 如下:
@Bean public SpringTemplateEngine templateEngine() { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.addTemplateResolver(new UrlTemplateResolver()); ... return templateEngine; }在 templatename :: selector中, templatename 和selector都可以是表达式。
<div th:replace="fragments/header:: ${#authentication.isAdmin()} ? 'header1' : 'header2'"> © 2016 The Static Templates </div>显式定义:
<!--在这里定义带参数的 th:fragment="alert (type, message)"--> <div th:fragment="alert (type, message)" th:assert="${!#strings.isEmpty(type) and !#strings.isEmpty(message)}" class="alert alert-dismissable" th:classappend="'alert-' + ${type}"> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> <span th:text="${message}">Test</span> </div>其他页面使用的时候传递参数给它:
<th:block th:if="${message != null}"> <div th:replace="fragments/alert :: alert (type=${#strings.toLowerCase(message.type)}, message=#{${message.message}(${#authentication.name})})"> </div> </th:block>Thymeleaf 3.0 新增方式 task/layout.html页面:
<head th:fragment="head(title, links, scripts)"> <title th:replace="${title}">Task List</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <link href="../../../resources/css/bootstrap.min.css" rel="stylesheet" media="screen" th:href="@{/resources/css/bootstrap.min.css}"/> <link href="../../../resources/css/core.css" rel="stylesheet" media="screen" th:href="@{/resources/css/core.css}"/> <!--/* Per-page placeholder for additional links */--> <th:block th:replace="${links}" /> <!--/* Per-page placeholder for additional scripts */--> <th:block th:replace="${scripts}" />其他页面:
<head th:replace="task/layout :: head(~{this :: title}, ~{this :: .custom-link}, ~{this :: .custom-script})"> <title>Task Details</title> <!-- 这块相同的就是`task/layout`页面共有的 --> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <link href="../../../resources/css/bootstrap.min.css" rel="stylesheet" media="screen" th:href="@{/resources/css/bootstrap.min.css}"/> <link href="../../../resources/css/core.css" rel="stylesheet" media="screen" th:href="@{/resources/css/core.css}"/> <!-- Custom links for this page only --> <link class="custom-link" href="../../../resources/css/task/task.css" th:href="@{/resources/css/task/task.css}" /> <!-- Custom scripts for this page only --> <script class="custom-script" src="../../../resources/js/task/task.js" th:src="@{/resources/js/task/task.js}"></script> </head>1.这个表达式灵活的地方就在于既拿到了模板页面的东西,又在模板页面的基础上添加了自己独有的东西。 2.单独打开task/layout.html页面会报错。
页面点击注册按钮弹出模态框:
<script th:inline="javascript" type="text/javascript"> /* Fill in modal with content loaded with Ajax */ $(document).ready(function () { $('#signup').on('click', function (e) { $("#myModal").modal(); $("#myModalBody").text(""); $.ajax({ url: "signup", cache: false }).done(function (html) { $("#myModalBody").append(html); }); }) }); </script> <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h4 class="modal-title" id="myModalLabel">Signup</h4> </div> <div class="modal-body" id="myModalBody">Lorem ipsum</div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> </div> </div><!-- /.modal-content --> </div><!-- /.modal-dialog --> </div><!-- /.modal -->可以看出上面的模态框内容是空白的,显示的内容是由ajax返回的数据。
在 signup/signup.html定义返回的 html (th:fragment="signupForm"):
<!DOCTYPE html> <html> <head> ... </head> <body> <form method="post" th:action="@{/signup}" th:object="${signupForm}" th:fragment="signupForm"> ... </form> </body> </html>在Controller中返回的字符串为 signup/signup :: signupForm指向了上面这个
private static final String SIGNUP_VIEW_NAME = "signup/signup"; @RequestMapping(value = "signup") public String signup(Model model, @RequestHeader("X-Requested-With") String requestedWith) { model.addAttribute(new SignupForm()); if (AjaxUtils.isAjaxRequest(requestedWith)) { return SIGNUP_VIEW_NAME.concat(" :: signupForm"); } return SIGNUP_VIEW_NAME; }效果查看需要在服务器上运行(官网说这个 Thymol 可以在不运行的时候查看 有时间再看吧)
我们还需要通过在模板引擎中添加额外的配置:
@Bean public SpringTemplateEngine templateEngine() { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); ... templateEngine.addDialect(new LayoutDialect()); return templateEngine; }task-ld/layout.html创建layout:fragment="content"
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <head>...</head> <body> <div th:replace="fragments/header :: header"></div> <div class="container"> <!--在这里设置layout布局--> <div layout:fragment="content">...</div> <div th:replace="fragments/footer :: footer">© 2017 The Static Templates</div> </div> </body> </html>在task-ld/task-list.html页面引用:
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{task-ld/layout}"> <head></head> <body> <div layout:fragment="content">...</div> </body> </html>注意<html>元素中的layout:decorate="~{task-ld/layout}" task-list.html中的layout:fragment="content"会替换 layout.html中的。其他东西继承过来。比如头尾。
task-list.html页面没有layout布局的时候: task-list.html页面有layout布局的时候:可以看出多了 头和尾
task-ld/alert.html页面设置layout:fragment
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"> <body> <th:block layout:fragment="alert"> <div class="alert alert-dismissable" th:classappend="'alert-' + ${type}"> <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> <h4 th:text="${header}">Alert header</h4> <!--/* 'layout:fragment' attribute defines a replaceable content section */--> <th:block layout:fragment="alert-content"> <p>Default alert content</p> </th:block> </div> </th:block> </body> </html>在task-ld/task-list.html页面调用:
<div layout:insert="~{task-ld/alert :: alert}" th:with="type='info', header='Info'" th:remove="tag"> <!--/* Implements alert content fragment with simple content */--> <th:block layout:fragment="alert-content"> <p><em>This is a simple list of tasks!</em></p> </th:block> </div>或者:
<div layout:insert="~{task-ld/alert :: alert}" th:with="type='danger', header='Oh snap! You got an error!'" th:remove="tag"> <!--/* Implements alert content fragment with full-blown HTML content */--> <th:block layout:fragment="alert-content"> <p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum.</p> <p> <button type="button" class="btn btn-danger">Take this action</button> <button type="button" class="btn btn-default">Or do this</button> </p> </th:block> </div>还是看这幅图,样式都调用到了,内容做了替换。
关于thymeleaf th:replace th:include th:insert 的区别
th:insert :保留自己的主标签,保留th:fragment的主标签。 th:replace :不要自己的主标签,保留th:fragment的主标签。 th:include :保留自己的主标签,不要th:fragment的主标签。(官方3.0后不推荐)这是第一篇博客,看的是tylmeleaf布局相关,后面继续看Thymeleaf的文档。ヾ(◍°∇°◍)ノ゙加油。