# Thymeleaf模板 页面布局(Page Layouts)

Thymeleaf模板 页面布局(Page Layouts)

官方文档地址

Thymeleaf标准布局系统

1.基础的

让我们简短的分析下包含语句:

<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 引用过来了,通过这种方式,我们可以在一个模板文件中定义多个片段,就像上面做的那样。

这里重要的是,所有的模板仍然可以是自然模板,并且可以在没有运行服务器的浏览器中查看。


2.通过标记选择器

通过使用标记选择器语法,类似 jQuery 选择器,thymeleaf 可以选择任意部分作为片段,而不用事先标记。
标记选择器语法地址

<div th:insert="https://www.thymeleaf.org :: div.description" >...</div>

上面的代码将包含一个来自thymeleaf.orgclass=“description”div

为了实现这一点,模板引擎必须配置为 UrlTemplateResolver 如下:

@Bean
public SpringTemplateEngine templateEngine() {
    SpringTemplateEngine templateEngine = new SpringTemplateEngine();    
    templateEngine.addTemplateResolver(new UrlTemplateResolver());
    ...
    return templateEngine;
}

3.使用表达式

templatename :: selector中, templatenameselector都可以是表达式。

<div th:replace="fragments/header:: ${#authentication.isAdmin()} ? 'header1' : 'header2'">
  &copy; 2016 The Static Templates
</div>

4.带参数的

显式定义:

<!--在这里定义带参数的 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">&times;</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})})">&nbsp;</div>
</th:block>

5.Fragment 表达式

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页面会报错。

来自Spring @Controller的 fragment

页面点击注册按钮弹出模态框:

<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">&times;</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 可以在不运行的时候查看 有时间再看吧)

Thymeleaf Layout Dialect

1.配置

<dependency>
  <groupId>nz.net.ultraq.thymeleaf</groupId>
  <artifactId>thymeleaf-layout-dialect</artifactId>
  <version>2.0.5</version>
</dependency>

我们还需要通过在模板引擎中添加额外的配置:

@Bean
public SpringTemplateEngine templateEngine() {
    SpringTemplateEngine templateEngine = new SpringTemplateEngine();
    ...
    templateEngine.addDialect(new LayoutDialect());
    return templateEngine;
}

2.创建一个布局

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">&copy; 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布局的时候:可以看出多了 头和尾
嵌套之后

Include style approach with Layout Dialect

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">&times;</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的文档。ヾ(◍°∇°◍)ノ゙加油。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值