Web 项目 tiger 之4 公共页抽取

本文导读

  • 本文承接《Web 项目 tiger 之3 登录与拦截》
  • 对于应用中公共的头部、左侧或右侧、甚至是底部区域,只要是共用的,就无需每个页面都重复去写,应该提取出来,大家引用即可。
  • JSP 可以使用 <jsp:include page=” ”...动态包含,同理 Thymeleaf 也有自己方式,可以查看其官方文本如下:

thymeleaf 公共页面元素抽取

抽取公共片段

  • 假设应用中需要一个公用的底部模块,如下所示 /templates/commonsFooter.html,使用 th:fragment 将其抽取为一个名字叫 "copy" 的代码片段
  • 以后在其它需要引用的地方可以使用 th:insert 、th:replace、th:include 等进行引用
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div th:fragment="copy">
     网站标识码bm0100001 京ICP备05070218号 京公网安备11010202000001号
</div>
</body>
</html>

引用公共片段

  • 三种引入公共片段的 th 属性:
  1. <div th:insert="footer :: selector|fragmentname"></div>:将公共片段整个插入到声明引入的元素中
  2. <div th:replace="footer :: selector|fragmentname"></div>:将声明引入的元素替换为公共片段
  3. <div th:include="footer :: selector|fragmentname"></div>:将被引入的片段的内容包含进这个标签中
  • 注意:selector 是选择器,如标签的id值等;fragmentname就是th:fragment 声明的片段名称
<!--1、比如抽取的公用代码片段如下-->
<footer th:fragment="copy">
    &copy; 2011 The Good Thymes Virtual Grocery
</footer>

<!--2、采用如下三种方式进行引用-->
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>

<!--3、则三种引用方式的效果分别对应如下-->
<div>
    <footer>
        &copy; 2011 The Good Thymes Virtual Grocery
    </footer>
</div>

<footer>
    &copy; 2011 The Good Thymes Virtual Grocery
</footer>

<div>
    &copy; 2011 The Good Thymes Virtual Grocery
</div>
  • 注意:th:insert 、th:replace、th:include 在标签中进行引用时可以不加 “~” 符号,也可以加,如下所示:
<div th:insert="~{footer :: #copy-section}"></div>
  • 但行内写法时,必须要加 "~":[[~{}]];[(~{})];

项目实战

抽取公共头部

  • 在登录进入后的用户列表页面,可以看到,可以将公告的头部和左侧菜单都可以抽取出来

  • 新建一个公用的页面 commons.html,然后将 userList.html 中的公用头部 <nav>元素剪切过来,同时进行公用代码抽取th:fragment

<!DOCTYPE html>
<!--xmlns写上之后 Thymeleaf就会有提示,更加方便-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<!--抽取公共的头部,使用 th:fragment 命名片段;
同理这个公用的文件(模板)中还可以设置其它的公用片段,如公用的左侧菜单,底部说明等-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="head">
    <!-- 获取session中的值,替换登录的用户账号-->
    <a class="navbar-brand col-sm-3 col-md-2 mr-0"
       href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" th:text="${session.userName}">Company name</a>
    <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
    <ul class="navbar-nav px-3">
        <li class="nav-item text-nowrap">
            <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
        </li>
    </ul>
</nav>
</body>
</html>

<body>

<!--在原来的位置引用公共的头部元素,原来的 <nav元素就是在这里的
commonsHead:模板名,根据Spring Boot配置的Thymeleaf映射查找
head:是模板中公用的代码片段
如果使用 th:insert 就会是div包裹nav了,所以采用 replace进行替换-->
<div th:replace="commons::head"></div>

<div class="container-fluid">

抽取公共左侧

<!DOCTYPE html>
<!--xmlns写上之后 Thymeleaf就会有提示,更加方便-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<!--抽取公共的头部,使用 th:fragment 命名片段;
同理这个公用的文件(模板)中还可以设置其它的公用片段,如公用的左侧菜单,底部说明等-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="head">
    <!-- 获取session中的值,替换登录的用户账号-->
    <a class="navbar-brand col-sm-3 col-md-2 mr-0"
       href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" th:text="${session.userName}">Company name</a>
    <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
    <ul class="navbar-nav px-3">
        <li class="nav-item text-nowrap">
            <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
        </li>
    </ul>
</nav>

<!--抽取的公共左侧菜单
除了 使用 th:fragment 命名片段名称标识,也可以直接根据选择器进行标识,如 id="commonsLeft"-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" id="commonsLeft">
    <div class="sidebar-sticky">
        <ul class="nav flex-column">
            <li class="nav-item">
                <a class="nav-link active" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-home">
                        <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
                        <polyline points="9 22 9 12 15 12 15 22"></polyline>
                    </svg>
                    Dashboard <span class="sr-only">(current)</span>
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file">
                        <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
                        <polyline points="13 2 13 9 20 9"></polyline>
                    </svg>
                    Orders
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-shopping-cart">
                        <circle cx="9" cy="21" r="1"></circle>
                        <circle cx="20" cy="21" r="1"></circle>
                        <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
                    </svg>
                    Products
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-users">
                        <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
                        <circle cx="9" cy="7" r="4"></circle>
                        <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
                        <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
                    </svg>
                    Customers
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-bar-chart-2">
                        <line x1="18" y1="20" x2="18" y2="10"></line>
                        <line x1="12" y1="20" x2="12" y2="4"></line>
                        <line x1="6" y1="20" x2="6" y2="14"></line>
                    </svg>
                    Reports
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-layers">
                        <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
                        <polyline points="2 17 12 22 22 17"></polyline>
                        <polyline points="2 12 12 17 22 12"></polyline>
                    </svg>
                    Integrations
                </a>
            </li>
        </ul>

        <h6 class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted">
            <span>Saved reports</span>
            <a class="d-flex align-items-center text-muted"
               href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
                     stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
                     class="feather feather-plus-circle">
                    <circle cx="12" cy="12" r="10"></circle>
                    <line x1="12" y1="8" x2="12" y2="16"></line>
                    <line x1="8" y1="12" x2="16" y2="12"></line>
                </svg>
            </a>
        </h6>
        <ul class="nav flex-column mb-2">
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Current month
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Last quarter
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Social engagement
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file-text">
                        <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
                        <polyline points="14 2 14 8 20 8"></polyline>
                        <line x1="16" y1="13" x2="8" y2="13"></line>
                        <line x1="16" y1="17" x2="8" y2="17"></line>
                        <polyline points="10 9 9 9 8 9"></polyline>
                    </svg>
                    Year-end sale
                </a>
            </li>
        </ul>
    </div>
</nav>

</body>
</html>

</head>

<body>

<!--在原来的位置引用公共的头部元素,原来的 <nav元素就是在这里的
commonsHead:模板名,根据Spring Boot配置的Thymeleaf映射查找
head:是模板中公用的代码片段-->
<div th:replace="commons::head"></div>

<div class="container-fluid">
    <div class="row">

        <!-- 在原来的左侧菜单位置引用抽取好的公共左侧菜单代码-->
        <div th:replace="commons :: #commonsLeft"></div>

        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
            <h2>Section title</h2>

链接高亮显示

需求分析

  • 说明:为了更加清晰已经方便说明,将原来公共的左侧菜单删除了部分内容,同时将第一个菜单项改为“用户列表”,第二个改为了“商品销量”
  • 现在用户登录之后默认进入用户列表页面,所以“用户列表”菜单项应该高亮显示,点击商品销量则“商品销量”高亮,这也是项目中必须要做的事情

可参数化片段签名

  • 实现链接动态高亮的功能需要使用到 Thymeleaf 的 参数化片段签名功能,即在引入片段的时候传传递参数过去,这在以前 JSP 中使用动态包含时也是这么做的
  • 在 Thymeleaf 的官方文档的 第8章第2节 有使用说明如下:
  1. 在 th:fragment 声明片段的时候可以同时声明参数,里面则可以使用这些参数的值
  2. 在 th:insert、th:replace、th:include 引用的时候就可以将参数值传递过去,传值的时候可以直接按顺序传递过去,也可以不按顺序但是按着参数名传递过去
8.2 Parameterizable fragment signatures
1) 
    In order to create a more function-like mechanism for template fragments, fragments         defined with th:fragment can specify a set of parameters:
<div th:fragment="frag (onevar,twovar)">
    <p th:text="${onevar} + ' - ' + ${twovar}">...</p>
</div>
2)
    This requires the use of one of these two syntaxes to call the fragment from th:insert or th:replace :
<div th:replace="::frag (${value1},${value2})">...</div>
3)
    Note that order is not important in the last option:
<div th:replace="::frag (onevar=${value1},twovar=${value2})">...</div>
<div th:replace="::frag (twovar=${value2},onevar=${value1})">...</div>
  • 对于根据“选择器”进行引用的,是无法声明参数的,所以 Thymeleaf 说明如下:即 th:fragment 或者 选择器 可以不用声明参数,而在引用的时候可以直接通过参数名将值传过去
Fragment local variables without fragment arguments
Even if fragments are defined without arguments like this:
<div th:fragment="frag">
    ...
</div>

We could use the second syntax specified above to call them (and only the second one):
<div th:replace="::frag (onevar=${value1},twovar=${value2})">

公共页 commons.html

<!DOCTYPE html>
<!--xmlns写上之后 Thymeleaf就会有提示,更加方便-->
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<!--抽取公共的头部,使用 th:fragment 命名片段;
同理这个公用的文件(模板)中还可以设置其它的公用片段,如公用的左侧菜单,底部说明等-->
<nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="head">
    <!-- 获取后台设置好的 session 中的值,显示当前登录的用户名
    如果是以前jsp的动态包含,则还需要<jsp:include page 的时候使用 <param子标签传值过来
    Thymeleaf 则在公共页面中也可以直接获取后台设置好的值
    这是因为 JSP 的动态包含是两个不同的 Servlet-->
    <a class="navbar-brand col-sm-3 col-md-2 mr-0"
       href="http://getbootstrap.com/docs/4.0/examples/dashboard/#" th:text="${session.userName}">Company name</a>
    <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
    <ul class="navbar-nav px-3">
        <li class="nav-item text-nowrap">
            <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">Sign out</a>
        </li>
    </ul>
</nav>

<!--抽取的公共左侧菜单
除了 使用 th:fragment 命名片段名称标识,也可以直接根据选择器进行标识,如 id="commonsLeft"-->
<nav class="col-md-2 d-none d-md-block bg-light sidebar" id="commonsLeft">
    <div class="sidebar-sticky">
        <ul class="nav flex-column">
            <li class="nav-item">
                <!-- 点击用户列表链接之后,请求后台地址,th:href 的"/"表示应用根地址,必须写
                 使用 Thymeleaf 的三元运算符,如果 activeUri的值为 userList 则设置class的属性值为 nav-link active
                 否则为 nav-link,其实 active 就是 BootStrop 的高亮样式而已
                 -->
                <a class="nav-link" th:class="${activeUri=='userList'?'nav-link active':'nav-link'}"
                   href="#" th:href="@{/userList}">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-file">
                        <path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
                        <polyline points="13 2 13 9 20 9"></polyline>
                    </svg>
                    用户列表
                </a>
            </li>

            <li class="nav-item">
                <!-- 请求后台控制器路径,同理进行参数值判断-->
                <a class="nav-link" th:class="${activeUri=='user/products'?'nav-link active':'nav-link'}"
                   th:href="@{/user/products}">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-shopping-cart">
                        <circle cx="9" cy="21" r="1"></circle>
                        <circle cx="20" cy="21" r="1"></circle>
                        <path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path>
                    </svg>
                    商品销量
                </a>
            </li>
            
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-users">
                        <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
                        <circle cx="9" cy="7" r="4"></circle>
                        <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
                        <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
                    </svg>
                    Customers
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-bar-chart-2">
                        <line x1="18" y1="20" x2="18" y2="10"></line>
                        <line x1="12" y1="20" x2="12" y2="4"></line>
                        <line x1="6" y1="20" x2="6" y2="14"></line>
                    </svg>
                    Reports
                </a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://getbootstrap.com/docs/4.0/examples/dashboard/#">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
                         fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
                         stroke-linejoin="round" class="feather feather-layers">
                        <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
                        <polyline points="2 17 12 22 22 17"></polyline>
                        <polyline points="2 12 12 17 22 12"></polyline>
                    </svg>
                    Integrations
                </a>
            </li>
        </ul>
    </div>
</nav>

</body>
</html>

用户列表页面 userList.html

  • 引用时传递参数的核心代码如下,其余内容就省去了
</head>

<body>

<!--在原来的位置引用公共的头部元素,原来的 <nav元素就是在这里的
commonsHead:模板名,根据Spring Boot配置的Thymeleaf映射查找
head:是模板中公用的代码片段-->
<div th:replace="commons::head"></div>

<div class="container-fluid">
    <div class="row">

        <!-- 在原来的左侧菜单位置引用抽取好的公共左侧菜单代码
        1、这是使用的 id选择器 进行的引用
        2、引用公共代码的片段的同时传递参数值过去
        3、参数值userList自行约定即可,也可以是1、a等字符,自己方便就行-->
        <div th:replace="commons::#commonsLeft(activeUri='userList')"></div>

        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
            <h2>Section title</h2>

            <div class="table-responsive">
                <table class="table table-striped table-sm">
                    <thead>
                    <tr>
                        <th>#</th>
                        <th>Header</th>
                        <th>Header</th>
                        <th>Header</th>
                        <th>Header</th>
                    </tr>

商品销量页面 products.html

  • 引用时传递参数的核心代码如下,其余内容就省去了
</head>

<body>
<!--在原来的位置引用公共的头部元素,原来的 <nav元素就是在这里的
commonsHead:模板名,根据Spring Boot配置的Thymeleaf映射查找
head:是模板中公用的代码片段-->
<div th:replace="commons::head"></div>

<div class="container-fluid">
    <div class="row">
        <!-- 在原来的左侧菜单位置引用抽取好的公共左侧菜单代码
        同理引用的同时传递参数值过去-->
        <div th:replace="commons::#commonsLeft(activeUri='user/products')"></div>

        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
            <div class="chartjs-size-monitor"

运行测试

  • 完全 ok

猜你喜欢

转载自blog.csdn.net/wangmx1993328/article/details/81380844
今日推荐