场景
使用Thymelaf 时,可以提取公共页面,比如侧边栏、需要公共引入的css、js文件、页脚等都可以提取出来。只编写业务页面的内容部分即可。
三种不同引入方式的区别
th:insert:将代码块片段整个插入到使用了th:insert的HTML标签中,
th:replace:将代码块片段整个替换使用了th:replace的HTML标签中,
th:include:将代码块片段包含的内容插入到使用了th:include的HTML标签中
用一个官方例子来区分三者的不同:
<!--th:fragment定义代码块标识-->
<footer th:fragment="copy">
© 2011 The Good Thymes Virtual Grocery
</footer>
<!--三种不同的引入方式-->
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
<!--th:insert是在div中插入代码块,即多了一层div-->
<div>
<footer>
© 2011 The Good Thymes Virtual Grocery
</footer>
</div>
<!--th:replace是将代码块代替当前div,其html结构和之前一致-->
<footer>
© 2011 The Good Thymes Virtual Grocery
</footer>
<!--th:include是将代码块footer的内容插入到div中,即少了一层footer-->
<div>
© 2011 The Good Thymes Virtual Grocery
</div>
实现
将公共的页面放在template目录下的layout目录下
采用从后往前的顺序来引用
最终业务开发页面代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"
th:replace="layout/layout(title='收货单数据',cssPaths='/public/css/plugins/datapicker/datepicker3.css,/public/css/plugins/switchery/switchery.css,/public/css/plugins/dropzone/basic.css,/public/css/plugins/dropzone/dropzone.css,/public/css/plugins/select2/select2.min.css,/public/css/plugins/dataTables/datatables.min.css,/public/css/plugins/daterangepicker/daterangepicker-bs3.css,/public/css/plugins/jsTree/style.min.css',jsPaths='/public/js/plugins/dataTables/datatables.min.js,/public/js/plugins/dataTables/dataTables.bootstrap4.min.js,/public/js/plugins/fullcalendar/moment.min.js,/public/js/plugins/jsTree/jstree.min.js,/public/js/plugins/sweetalert/sweetalert2.all.min.js,/public/js/plugins/ladda/spin.min.js,/public/js/plugins/ladda/ladda.min.js,/public/js/plugins/ladda/ladda.jquery.min.js,/public/js/plugins/select2/select2.full.min.js,/public/js/plugins/dropzone/dropzone.js,/public/js/plugins/switchery/switchery.js,/public/js/plugins/daterangepicker/daterangepicker.js,/public/js/plugins/datapicker/bootstrap-datepicker.js,/public/js/plugins/validate/jquery.validate.min.js,/public/js/plugins/validate/validate_zh.js,/modular/utils.js,/modular/receiveOrder/wmsReceiveOrder.js')"><!-- layout文件路径-->
<div th:fragment="content">
<div class="ibox float-e-margins">
<div class="ibox ">
<div class="ibox-title">
<h5>条件搜索</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
</div>
</div>
<div class="ibox-content">
<table class="table my-minus-1 mb-minus-1">
<tbody>
<tr>
<td>
<div class="row" id="searchCondition">
<div class="col-sm-2">
<div class="form-group">
<label class="col-form-label" for="purchaseCode">收货单号</label>
<input type="text" id="purchaseCode" name="purchaseCode" value="" placeholder="收货单号" class="form-control">
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<label class="col-form-label" for="supplierName">供应商名称</label>
<input type="text" id="supplierName" name="supplierName" value="" placeholder="供应商名称" class="form-control">
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<label class="col-form-label" for="status">状态</label>
<select class="form-control" id="status" name="status">
<option value="">全部</option>
<option th:each="result : ${codeList}" th:value="${result.codeValue}" th:text="${result.codeName}"></option>
</select>
</div>
</div>
</div>
</td>
</tr>
</tbody>
<tfoot>
<tr class="text-center">
<td colspan="4">
<button id="resetBtn" class="btn btn-info mt-2" type="button"><i class="fa fa-reply"></i> 重置</button>
<button id="searchBtn" class="btn btn-info mt-2" type="button"><i class="fa fa-search"></i> 搜索</button>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
<div class="ibox-content">
<div class="table-responsive">
<P>
<shiro:hasPermission name="roleAdd">
</shiro:hasPermission>
<button id="detailBtn" class="btn btn-info " type="button"><i class="fa fa-eye"></i> 查看</button>
<button id="delBtn" class="btn btn-info " type="button"><i class="fa fa-trash-o"></i> 删除</button>
<button id="submitBtn" class="btn btn-info " type="button"><i class="fa fa-arrow-up"></i> 提交</button>
<button id="importBtn" class="btn btn-info " type="button"><i class="fa fa-file-excel-o"></i> 导入</button>
<button id="printBtn" class="btn btn-info " type="button"><i class="fa fa-print"></i> 打印</button>
<button id="dowloadBtn" class="btn btn-info " type="button"><i class="fa fa-download"></i> 模板下载</button>
<button id="InOrderBtn" class="btn btn-info " type="button"><i class="fa fa-plus"></i> 生成入库单数据</button>
<button id="refreshBt" class="btn btn-info " type="button"><i class="fa fa-refresh"></i> 刷新</button>
</P>
<p>
</p>
<table id="wmsReceiveOrder_table_id" class="table table-striped table-bordered hover" style="width:100%">
<thead>
<tr>
<th>序号</th>
<th>收货单号</th>
<th>收货日期</th>
<th>收货人</th>
<th>供应商编号</th>
<th>供应商名称</th>
<th>总托数</th>
<th>总件数</th>
<th>送货单号</th>
<th>创建人</th>
<th>创建日期</th>
<th>状态</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal inmodal" id="apImportModel" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" id="apImportDiv" th:fragment="apImportDiv">
<div class="modal-content animated fadeIn">
<button type="button" class="close" onclick="return Testclose();" id="closeUploadBtn"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<form class="dropzone" id="dropzoneForm" enctype="multipart/form-data">
<div class="fallback">
<input name="file" value="1M以内的Excel文件" type="file" id="file_id" accept=".xls,.xlsx" onchange="fileChange(this);" />
</div>
</form>
<button id="uploladBtn" class="btn btn-info mt-2" type="button" onclick="return uploadExcel()"><i class="fa fa-reply"></i>上传</button>
<button id="parseBtn" class="btn btn-info mt-2" type="button" onclick="return parseExcel()"><i class="fa fa-reply"></i>导入</button>
</div>
</div>
</div>
<!-- 查看详情弹窗显示-->
<div class="modal inmodal" id="receiveOrderDetailsModel" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" id="receiveOrderDetailsDiv" th:fragment="receiveOrderDetailsDiv">
<div class="modal-content animated fadeIn">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
</div>
</div>
</div>
</div>
</html>
注:
1.此页面通过th:replace来添加需要引用的css和js文件,即用layput目录下的layout.html来代替,并传递三个参数,一个是页面标题,一个是CSS路径,一个是js路径。
2.th:fragment部分就是声明一个代码块,是主要的业务代码部分。
来到引用的layout.html
layout是控制整个页面布局的模板文件。
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org" >
<head th:replace="layout/header::head(${title},${cssPaths})"></head>
<body>
<div id="wrapper">
<div th:replace="layout/slider::silder()"></div>
<div id="page-wrapper" class="gray-bg" >
<div th:replace="layout/navbar::navbar()"></div>
<div class="wrapper wrapper-content animated fadeInRight">
<div th:include="::content"></div>
</div>
<div class="footer">
<div class="pull-right">
<a href="https://blog.csdn.net/BADAO_LIUMANG_QIZHI" target="_wongoing">霸道 </a>技术支持
</div>
<div>
<strong>流氓</strong> 气质管理系统
</div>
</div>
</div>
</div>
</body>
<footer th:replace="layout/footer::foot(${jsPaths})"></footer>
</html>
注:
1.head部分通过th:replace来使用layout目录下的header.html下的head代码块(即使用th:fragment=”head(title,cssPaths)标识的部分)来代替,并将从上个页面接收到的参数再传递给head代码块。
2.再往下使用layout目录下的slide.html中的silder代码块来代替,使用公共侧边栏,下面同理引入导航栏。
3.再往下使用 th:include来引进当前页面的content代码块,即上个页面使用<div th:fragment=”content”>声明的部分。
4.再往下就是公共的页脚部分,没有抽取公共页面,直接写死即可。
5.再往下就是使用th:replace引用的页脚部分,接受上个页面传递的js路径参数,并传递给layout目录下的footer.html中的foot代码块。
引入的head页面代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head th:fragment="head(title,cssPaths)">
<title th:text="${title}"></title>
<meta charset="UTF-8"/>
<meta name= "viewport"content="width=device-width, initial-scale=1.0">
<!--begin::基础样式 -->
<link th:href="@{/public/css/bootstrap.min.css}" rel="stylesheet">
<link th:href="@{/public/font-awesome/css/font-awesome.css}" rel="stylesheet">
<link th:href="@{/public/css/animate.css}" rel="stylesheet">
<link th:href="@{/public/css/style.css}" rel="stylesheet">
<link th:href="@{/public/css/my-style.css}" rel="stylesheet">
<!--end::基础样式 -->
<!--begin::页面样式 -->
<link rel="stylesheet" type="text/css" th:each="cssPaths,status:${#strings.setSplit(cssPaths,',')}" th:href="@{${cssPaths}}"/>
<!--end::页面样式 -->
</head>
</html>
注:
1.通过th:fragment=”head(title,cssPaths)接收上个页面传递过来的参数,标题和CSS路径。
2.通过th:text=”${title}”动态显示标题。
3.然后引用一些基础样式,引用href属性通过@符号来引用。
4.然后分隔接受的cssPath参数,通过循环依次引入,使用内置变量通过#strings.setSplit,使用#来使用。使用${cssPaths}接受上个页面传递的参数。使用@符号使用href属性。
引入的silder页面代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<nav class="navbar-default navbar-static-side" role="navigation" th:fragment="silder()">
<div class="sidebar-collapse">
<ul class="nav metismenu" id="side-menu">
</ul>
</div>
</nav>
</html>
引入的navbar页面代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<div class="row border-bottom" th:fragment="navbar()">
<nav class="navbar navbar-static-top white-bg" role="navigation" style="margin-bottom: 0">
<div class="navbar-header">
</div>
<ul class="nav navbar-top-links navbar-right">
<li>
<a th:href="@{/logout}">
<i class="fa fa-sign-out"></i> 退出
</a>
</li>
</ul>
</nav>
</div>
</html>
注:
1.只是抽取了退出按钮,其中退出的href属性通过th:href=”@{/logout}”来引用,跳转到退出登录对应的url。
引入的foot页面代码
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<footer th:fragment="foot(jsPaths)">
<!--begin::基础js -->
<!-- Mainly scripts -->
<script th:src="@{'/public/js/jquery-3.1.1.min.js?t='+${#strings.randomAlphanumeric(9)}}"></script>
<script th:src="@{'/public/js/popper.min.js?t='+${#strings.randomAlphanumeric(9)}}"></script>
<script th:src="@{'/public/js/bootstrap.min.js?t='+${#strings.randomAlphanumeric(9)}}"></script>
<script th:src="@{'/public/js/plugins/metisMenu/jquery.metisMenu.js?t='+${#strings.randomAlphanumeric(9)}}"></script>
<script th:src="@{'/public/js/plugins/slimscroll/jquery.slimscroll.min.js?t='+${#strings.randomAlphanumeric(9)}}"></script>
<!-- Custom and plugin javascript -->
<script th:src="@{'/public/js/inspinia.js?t='+${#strings.randomAlphanumeric(9)}}"></script>
<script th:src="@{'/public/js/plugins/pace/pace.min.js?t='+${#strings.randomAlphanumeric(9)}}"></script>
<script th:src="@{'/public/js/cookie.js?t='+${#strings.randomAlphanumeric(9)}}"></script>
<!--end::基础js -->
<!--begin::页面js -->
<script th:each="jsPaths,status:${#strings.setSplit(jsPaths,',')}" th:src="@{${jsPaths}+'?t='+${#strings.randomAlphanumeric(9)}}"></script>
<!--end::页面js -->
<script th:src="@{'/modular/index.js?t='+${#strings.randomAlphanumeric(9)}}"></script>
</footer>
</html>
注:
1.大体思路同上面的cssPath路径的解析引用。
2.这里在每个引用的js后面追加了一个9位的随机数,掩人耳目。