Thymeleaf提取公共页面(从实例入手,以inspinia模板为例)

  • Post author:
  • Post category:其他


场景

使用Thymelaf 时,可以提取公共页面,比如侧边栏、需要公共引入的css、js文件、页脚等都可以提取出来。只编写业务页面的内容部分即可。

三种不同引入方式的区别

th:insert:将代码块片段整个插入到使用了th:insert的HTML标签中,

th:replace:将代码块片段整个替换使用了th:replace的HTML标签中,

th:include:将代码块片段包含的内容插入到使用了th:include的HTML标签中


用一个官方例子来区分三者的不同:

<!--th:fragment定义代码块标识-->
<footer th:fragment="copy">
&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>
    &copy; 2011 The Good Thymes Virtual Grocery
    </footer>
</div>

<!--th:replace是将代码块代替当前div,其html结构和之前一致-->
<footer>
&copy; 2011 The Good Thymes Virtual Grocery
</footer>
<!--th:include是将代码块footer的内容插入到div中,即少了一层footer-->
<div>
&copy; 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">&times;</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">&times;</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位的随机数,掩人耳目。



版权声明:本文为BADAO_LIUMANG_QIZHI原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。