1.公共部分抽取问题
- 首先是dashboard.html页面跳转"员工管理"页面的a标签的href属性改造
- 创建一个controller:EmployeeController,用于控制一切有关雇员的视图跳转和参数传递
package com.thhh.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/employee") public class EmployeeController { @RequestMapping("/list") public String EmployeeList(){ return "Employee/list.html"; } }
- a标签属性修改
<a class="nav-link" th:href="@{/employee/list}">
- 同时将员工信息页面的超链接也改了,免得跳转之后再次点击跳转回这个静态资源的在线页面上了
<a class="nav-link" th:href="@{/employee/list}">
- 测试
- 使用thymeleaf抽取视图公共部分
- 视图的公共部分一眼就能看出来:顶部导航栏和侧边栏
- thymeleaf中公共模块引用/使用表达式:
Fragment Expressions: ~{...}
- 在thymeleaf中可以使用
th:fragment=“抽取的模块的名称”
抽取视图模板中的公共部分/模块实现重用,并使用th:insert="~{文件位置::抽取抽来的模板的名称}"
或th:replace="~{文件位置::抽取抽来的模板的名称}"
去引用抽取出来的公共部分 - 使用
th:insert
会新增一个div,使用th:replace
直接替换当前标签,所以相比之下,th:replace
使用的更多 - 抽取的时候我们可以直接在某一个页面上的公共部分的标签添加
th:fragment
实现抽取,我们也可以单独定义一个公共html文件/commons/common.html存储公共的部分/模块(就是直接把页面上重复的部分的代码剪切出来粘贴到/commons/common.html中)
- 直接使用/commons/common.htm的方法抽取
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--头部导航栏--> <nav class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0" th:fragment="topbar"> <a class="navbar-brand col-sm-3 col-md-2 mr-0" th:href="@{/main.html}">[[${session.userInfo}]]</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" th:href="@{/index.html}">注销</a> </li> </ul> </nav> <!--侧边栏--> <div class="sidebar-sticky" th:fragment="sidebar"> <ul class="nav flex-column"> <li class="nav-item"> <a class="nav-link active" th:href="@{/main.html}"> <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> 首页 <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" th:href="@{/employee/list}"> <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> 员工管理 </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> </body> </html>
-
引用th抽取出来的公共模块
-
测试
-
从上面的测试结果来看,抽取的模块在引入的页面成功应用;抽取的最大好处就是实现了复用,并且修改的时候只需要修改抽取的模板就可以实现全局的修改
2.高亮问题
- 查看素材源码
- 可见上面的4个侧边栏li标签中,第一个最大的不太就是多写了一个active
- 解决:我们可以在
th:replace="~{commons/common::sidebar}"
中传递参数,直接通过(将参数加在最后即可),<div th:replace="~{commons/common::sidebar(active='main.html')}"></div>
; - 参数为(active=‘main.html’)
- 即在引用抽象出来组件的地方可以传递参数,那么接收参数的地方就是我们抽象出来的组件;我们就依据获取到的参数+三目运算符一起决定某一个li的class中是不是加上active使其高亮
- thymeleaf的三目运算符:If-then-else: (if) ? (then) : (else),可以发现语法和Java中一样
- 注意:thymeleaf的三目运算符非常常用,要记住怎么使用
<a th:class="${active=='main.html'?'nav-link active':'nav-link'}" th:href="@{/main.html}">
- 通了在员工管理的li中的a标签上加上相同的取值操作和3目判断
- 测试
- 测试成功!但是我们需要为每一个侧边栏的a标签的class都加上参数判断,为每一个引用公共模块的地方加上参数传递,并且参数的值各不相同
3.小结
- 员工列表展示功能实现遇到的困难/要解决的问题
- 提取页面中的公共模块
- 在thymeleaf中可以使用
th:fragment=“抽取的模块的名称”
抽取视图模板中的公共部分/模块实现重用,并使用th:insert="~{文件位置::抽取抽来的模板的名称}"
或th:replace="~{文件位置::抽取抽来的模板的名称}"
去引用抽取出来的公共部分 - 我们更多的时候会使用
th:replace="~{文件位置::抽取抽来的模板的名称}"
去引用抽取出来的公共部分,因为th:replace是替代当前元素,而th:insert是增加一个div - 如果引入的地方需要向公共部分传递参数,则直接在
th:replace="~{文件位置::抽取抽来的模板的名称}"
后面加上(变量名称=“变量值”)(th:replace="~{文件位置::抽取抽来的模板的名称(变量名称="变量值")}"
),在抽取出来的公共模块直接使用${变量名称}获取传递的值即可
- 在thymeleaf中可以使用
- 提取页面中的公共模块
4.后台数据渲染问题
- 首先还是观察前端素材的源码和视图效果之间的对应关系
- 按照自己的需求对其进行修改
- 首先修改表头上的字段/属性名称,按照pojo中的Employee的成员属性来设置
- 接下来就是表体,我们知道表体的数据一定是通过循环遍历出来的
- thymeleaf中的遍历语法
th:each
,用法:th:each="用于存储每一个遍历出来的元素的临时变量 : ${后端传回来的集合变量}"
<table class="table table-striped table-sm"> <thead> <tr> <th>id</th> <th>lastName</th> <th>email</th> <th>gender</th> <th>department</th> <th>birth</th> </tr> </thead> <tbody> <tr th:each="emp:${emps}"> <td th:text="${emp.getId()}"></td> <td th:text="${emp.getLastName()}"></td> <td th:text="${emp.getEmail()}"></td> <td th:text="${emp.getGender()}"></td> <td th:text="${emp.department.getDepartmentName()}"></td> <td th:text="${emp.getBirth()}"></td> </tr> </tbody> </table>
- 测试
- 但是光有数据还不够,我们还应该可以通过前端操作数据才行,所以我们需要在表格中加入操作列,并存入对应操作的按钮
- 当然,上面能正常的显示,还做了一些其他的调整,包括行高调整、文本居中,依据三目运算符判断性别显示等等,这些操作比较简单,在上图代码中都有显示
- 现在要解决的是日期的显示问题,因为我们的都是在dao层造的假数据,并且都是直接使用new Date()现用现造出来的,所以时间格式和我们想要看到的不符合
- 解决这个问题方法有两个:①直接在new Date()的时候使用 ②使用thymeleaf的工具类
- 代码
<td style="line-height: 40px" th:text="${#dates.format(emp.getBirth(),'yyyy/MM/dd HH:mm:ss')}"></td>
- 注意:具体显示的日期格式我们可以自定义,即
${#dates.format(date,'格式自定义')}
- 测试
- 测试成功!
5.小结
- 到此,"展示员工列表"功能实现就完成了,注意:本篇博客主要讲解的是展示数据,重点在展示,所以表格中最后一行的"删除、修改、新增"按钮的功能还没有添加,这些功能将在后几篇博客中进行实现
- 在上面的实现过程中,我们基本步骤就是:需求分析–观察前端素材代码–写一个controller和视图模板交互数据–使用thymeleaf解析数据进行展示
- 通过上面的实现,我们又学习和巩固了thymeleaf的语法知识
th
:接管标签参数@{...}
:th中取url,注意使用thymeleaf跳转视图,a标签的href属性必须被th接管,否则不能跳转/templates/下的视图th:fragment=“抽取的模块的名称”
抽取视图模板中的公共部分/模块实现重用Fragment Expressions: ~{...}
:thymeleaf抽取公共视图部分实现复用th:insert="~{文件位置::抽取抽来的模板的名称}"
或th:replace="~{文件位置::抽取抽来的模板的名称}"
去引用抽取出来的公共部分th:replace="~{文件位置::抽取抽来的模板的名称(参数列表)}"
实现模块引用向模块传递参数,从而实现不同的显示效果th:each="用于存储每一个遍历出来的元素的临时变量 : ${后端传回来的集合变量}"
:用于遍历集合数据进行前端数据渲染${#dates.format(date,'格式自定义')}
:格式化前端展示的日期格式
- 表达式取值小结(仅仅按照现在用到的用法做的小结)
${...}
:取变量,无论是后端返回的变量还是前端页面上的变量都可以取到#{...}
:取国际化的时候在配置文件中配置的key#{...}
:配合thymeleaf跳转/templates/下的视图模板~{...}
:用于引用抽取出来的公共模块