SpringBoot使用thymeleaf实现布局方案一,不懂就out了(循序渐进的超级详细讲解方式) - 第424篇

导读

       在搭建一个网页的时候,一般的会分为header、content、footer,也就是导航部分、中间的内容部分、以及底部。对于header和footer这两个部分一般的是很多页面公用的,那么这时候,我们会把公共的部分进行抽离出来,这就是所谓的thymeleaf布局。

       这一节就到大家来看看其中的一种布局方案。

一、准备工作

       在具体讲解布局方案之前,我们一起先来大家一个基本的页面,包含header、content以及footer。

       在具体的讲解之前,说明一下基本的环境:

(1)OS:Mac OS

(2)Spring Boot版本:2.6.7

(3)JDK:1.8

(4)thymeleaf:3.0

在使用idea构建的时候,默认选择的是11。现在都jdk十几了,我是不是有必要也升级到比较新的版本呢?亲爱的粉丝,你们觉得呢?

1.1 构建项目

       使用Idea工具构建一个spring boot项目,取名为springboot-thymeleaf-layout。

       啥,你说你不喜欢这个名称,那你随意,只要你开心,想取啥就取啥,O(∩_∩)O哈哈~

1.2 页面映射

       编写一个Controller,当访问/index的时候,访问index.html页面

package com.kfit.website.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;/** * *  官网的控制器 * * @author 悟纤「公众号SpringBoot」 * @date 2022-04-23 * @slogan 大道至简 悟在天成 */@Controllerpublic class WebsiteController {    /**     * 跳转到首页页面     * @return     */    @RequestMapping(value = {"/index","/"})    public String index(){        return "/index";    }}

1.3 index.html页面

       接下来就是页面了,在resources/templates先创建index.html:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <!-- 导航部分 -->    <header style="text-align: center;height: 40px;background: cadetblue;"> 首页 | 产品 | 关于我们 </header>    <!-- 内容部分 -->    <div  style="text-align: center;;height: 150px;">内容部分</div>    <!-- 顶部部分 -->    <footer style="text-align: center;;height: 40px;background: #2e2e41;color:white;">@版权所有 公众号SpringBoot</footer></body></html>

说明:在实际中,样式部分以及前端页面有前端工程师进行编写,这里仅仅是示例。当然你如果你也会前端技术的话,那么你就是别人家的孩子了——全栈架构师,牛牪犇逼。

1.4 启动测试

       启动应用访问地址:

http://127.0.0.1:8080/index

二、使用include/replace/insert进行布局

       在前端的<header>、<footer>是写在了index.html中,我们紧接着编写product.html,aboutus.html会发现它们也需要<header>、<footer>,而且基本上是大同小异,如果非得说有区别的话,那就是当前页面的的时候,可能会高亮。

       那么我们就得思考,这样子的话<header>、<footer>就应该抽离出来变成公共的部分,当你在开发的时候,到这一步就能想到后面发生的很多步,以此来进行设计,这个就是架构,一不小心你还在开发工程师的时候,就拥有了架构思维。

       那么公共部分怎么抽离出来呢,这就是本节的重点th:include和th:replace。

2.1 抽离出来header和footer

       首先将header和footer抽离出来,定义两个页面header和footer。

       对应的common/header.html代码:

<!-- 导航部分 --><header style="text-align: center;height: 40px;background: cadetblue;"> 首页 | 产品 | 关于我们 </header>

2.2 使用include/replace引入

       接下来就是使用th:include/th:replace引入header.html和footer.html。

       对于th:include/th:replace有什么区别呢?

(1)th:include:引入子模块的children,依然保留父模块的tag。加载模板的内容:读取加载节点的内容(不含节点名称),替换div内容

(2)th:replace:引入子模块的所有,不保留父模块的tag。替换当前标签为模板中的标签,加载的节点会整个替换掉加载他的div

       先看下th:include的方式,在index.html的代码就会变成:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <header th:include="common/header.html"></header>    <!-- 内容部分 -->    <div  style="text-align: center;;height: 150px;">内容部分</div>    <footer th:include="common/footer.html"></footer></body></html>

       运行效果是一样的,主要看下th:include生成的源码:

依然保留父模块的tag<header>。加载模板的内容:读取加载节点的内容(不含节点名称),替换div内容

              接下来看下th:replace的方式,在index.html的代码就会变成:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <header th:replace="common/header.html"></header>    <!-- 内容部分 -->    <div  style="text-align: center;;height: 150px;">内容部分</div>    <footer th:replace="common/footer.html"></footer></body></html>

       运行效果是一样的,主要看下th:replace生成的源码:

       不保留父模块的tag<header>。替换当前标签为模板中的标签,加载的节点会整个替换掉加载他的div

2.3 thymleaf3.0的insert

       Thymeleaf 3.0 之后不再推荐使⽤ th:include.

l  th:insert:将被引用的模板片段插⼊到自己的标签体中

l  th:replace:将被引用的模板片段替换掉自己

l  th:include:类似于 th:insert,⽽不是插⼊⽚段,它只插⼊此⽚段的内容。

看下insert生成的效果:

       可以看到这里的效果和th:include很类似,暂时看不出来区别。

2.4 th:fragment代码片段加载

       对于header和footer可以单独一个页面,也可以在同一个页面,那么这时候,怎么确定要加载哪一部分呢?th:fragment就派上用场了。fragment有碎片; 片段之意,也就是定义一段代码碎片标识。

       首先定义common.html,包含header.html和footer.html的代码:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <!-- 导航部分 -->    <header th:fragment="header" style="text-align: center;height: 40px;background: cadetblue;"> 首页 | 产品 | 关于我们 </header>    <!-- 顶部部分 -->    <footer th:fragment="footer" style="text-align: center;;height: 40px;background: #2e2e41;color:white;">@版权所有 公众号SpringBoot</footer></body></html>

说明:这里定义了代码片段header和footer,通过th:fragment进行指定。

       仅紧着看下index.html的代码,也可以新建一个index2.html进行测试:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <header th:insert="common/common::header"></header>    <!-- 内容部分 -->    <div  style="text-align: center;;height: 150px;">内容部分</div>    <footer th:insert="common/common::footer"></footer></body></html>

       使用th:insert生成的源码:

       使用th:include生成的源码:

       <header标签的样式不见了,那么效果就会变成:

使用th:replace生成的源码:

       从这里就可以看出th:insert和th:include的区别了?具体区别,自己仔细观察生成的源码,自行总结下。

       到这里,我先说明一下,大部分情况下建议使用th:replace,可以看出生成的代码干净利落,不出现多余的父类标签。当然如果你的父类标签有样式的时候,那么就使用th:insert。

2.5 当前页面公用部分引入

       在一个页面中,也会出现有些部分的代码样式是一样的,你可以把这部分叫做模板。

       那么当前页面的样式如何引入呢?小子们上代码:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <header th:replace="common/common::header"></header>    <!-- 内容部分 -->    <div  style="text-align: center;height: 150px;">内容部分</div>    <div th:include="::#pageCommon"></div>    <footer th:replace="common/common::footer"></footer><template id="pageCommon">    <div style="text-align: center;">页面公用部分</div></template></body></html>

说明:

(1)使用::#pageCommon,元素选择器的方式就可以引入了。

(2)<template>标签:标记用作容纳页面加载时对用户隐藏的 HTML 内容的容器。如果您有一些需要重复使用的 HTML 代码,则可以使用 <template> 标记。

       效果:

此时生成的源代码:

       这里就不能使用th:insert和th:replace了,看下生成的源码:

       看源码会发现,此时<template>节点也被携带过来了,由于<template>隐藏特性,内容根本不会显示出来:

       有人会问,我就是想喜欢th:replace,我们老大说只能使用th:replace,那么此时怎么破呢?这个也很好破,只需要稍微修改一个地方即可:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <header th:replace="common/common::header"></header>    <!-- 内容部分 -->    <div  style="text-align: center;height: 150px;">内容部分</div>    <div th:replace="::#pageCommon"></div>    <footer th:replace="common/common::footer"></footer><template>    <div id="pageCommon" style="text-align: center;">页面公用部分</div></template></body></html>

       细心的网页肯定发现了,我这里这是把id移动到了内部div上,这时候就可以使用th:replace了,看下生成的源码:

       但是这里会引发出来一个新的问题,什么问题呐?我们在一开始说到到,对于<template>是页面的公共内容,那么很显然会被多处引入,而这里的div的id为pageCommon,很显然要对这个元素操作的时候就麻烦了。

       那么针对这种情况怎么破呢?很简单,这里提供关键词:选择器。

2.6 参数传递

       很多时候,我们的common.html也会有一些不一样的地方,比如首页激活的时候,会多出来一个class属性,那么一方面可以根据页面地址的不同进行条件的判断,另外一方面就是是否在引入代码的时候,是否可以引入参数呢?

       需要先修改common.html,当然也可以复制出来一份common2.html,允许参数的传递:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <!-- 导航部分 -->    <header th:fragment="header(param1,param2)" style="text-align: center;height: 40px;background: cadetblue;">        首页 | 产品 | 关于我们 - <span th:text="${param1} +'--'+ ${param2}"></span>    </header>    <!-- 顶部部分 -->    <footer th:fragment="footer" style="text-align: center;;height: 40px;background: #2e2e41;color:white;">@版权所有 公众号SpringBoot</footer></body></html>

       然后修改index.html进行参数传递,也可以复制出来一份index3.html:

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <header th:replace="common/common2::header('/index.html',1000)"></header>    <!-- 内容部分 -->    <div  style="text-align: center;height: 150px;">内容部分</div>    <footer th:replace="common/common2::footer"></footer></body></html>

       效果:

       可以获取到参数之后,那么就可以根据这些参数进行一些特殊的处理了。

总结

       最后和大家总结下:

(1)布局方案th:include/th:replace/th:insert,其中include在thymeaf在3.0之后就不推荐使用了。

(2)代码片段th:fragment,在一个页面可以定义多段代码片段,以此通过th:replace=“common:: fragmentId”的方式引入不通过的代码片段。

(3)参数的传递:在使用th:fragment的时候,可以接一个参数列表。

       这节就先到这里,对于th:include/th:replace/th:insert或者thymeleaf的使用你还有其它的疑问吗?请留言!

  1. 我就是我,是颜色不一样的烟火。
  2. 我就是我,是与众不同的小苹果。


购买完整视频,请前往:http://www.mark-to-win.com/TeacherV2.html?id=287