备忘录《六》thymeleaf 使用学习总结、避免再次踩坑

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/liaohaojian/article/details/85717156

       最近使用Spring boot2+thymeleaf做了一个项目,由于第一次使用thymeleaf,所有遇到很多坑,不过更多坑是其他人写的博客,最让我无语的是,是我搜索如何在onclick里传对象,基本没有一个说对的,最坑的是,明明thymeleaf不允许在th:onclick中传String类型,他们写的博客都是传int的,他们自以为这个就是正确的传参,好吧,无语。真的博客十有八九都有小问题。

下面列举出,我在项目中使用到的标签,在此这里记录一下,以作整理与分享。

1.th:onclick(注意,onclick动态传参时,只能传入numbers or booleans 类型,不然会报错:Only variable expressions returning numbers or booleans are allowed in this context, any other datatypes are not trusted in the context of this expression, including Strings or any other object that could be rendered as a text literal. A typical case is HTML attributes for event handlers (e.g. "onload"), in which textual data from variables should better be output to "data-*" attributes and then read from the event handler. )文档写的很清楚了,其他类型可以通过data-*传递,实际项目中,其实我们一般都是传对象到JS,虽然thymeleaf有直接传对象到JS的,但是很局限,不符合实际要求,下面说一下我的做法。

首先我在返回的model中重写toString方法,把该model对象提前转成了json

@Override
public String toString() {
      /*返回的字符串当中不能包含富文本,不然前端赋值给某个属性时会报错*/
       return publicUtil.replaceBlank(JSONObject.fromObject(this).toString());
}

/**
* publicUtil工具类,去除字符串空格
 * @param str
 * @return
 */
public static String replaceBlank(String str) {
	String dest = "";
	if (str!=null) {
		Pattern p = Pattern.compile("\\s*|\t|\r|\n");
		Matcher m = p.matcher(str);
		dest = m.replaceAll("");
	}
	return dest;
}

html页面引用时,通过data-*传递

<a href="javascript:void(0)"  th:attr="data-account=${cloudCollection.toString()}"  οnclick="toLookCloudDetail(this,'1')"> 
<img th:src="${#httpServletRequest.getContextPath()}+'/images/see.png'" data-toggle="tooltip" data-placement="bottom" title="查看详情"></a>

重点查看th:attr="data-account=${cloudCollection.toString()}",F12查看源代码后,你会发现这个写法,data-account里面的值就是我们需要获取的对象,下面js接收

function toLookCloudDetail(obj,n){
  var arr = JSON.parse($(obj).attr("data-account"));//将一个 JSON 字符串转换为对象。
}

2.th:include、th:replace(一般用于引入公共页面,如顶部底部页面,公共方法页面)

不同点:

  • th:include:加载模板的内容: 读取加载节点的内容(不含节点名称),替换div内容
  • th:replace:替换当前标签为模板中的标签,加载的节点会整个替换掉加载他的div 

举个例子,假如我们公共模板如下

<!-- th:fragment 定义用于加载的块 -->
<span th:fragment="pagination"> 
This is public pagination
</span>

 我们通过2个标签引用进来

================= th:include 和 th:replace============================
<!-- 加载模板的内容: 读取加载节点的内容(不含节点名称),替换<div>的内容 -->
<div th:include="pagination::pagination">1</div>
<!-- 替换当前标签为模板中的标签: 加载的节点会整个替换掉加载他的<div>  -->
<div th:replace="pagination::pagination">2</div>

这时你F12查看源码时,你会发现他们的区别

<!-- 加载模板的内容: 只读取加载节点的内容(不含节点名称),替换<div>里面的内容 -->
<div> This is public pagination</div>
<!-- 替换当前标签为模板中的标签: 加载的节点会替换掉原来的<div>  -->
<span> This is public pagination</span>

3.th:each 遍历

<tr th:each="user,sta:${userlist}" th:class="${sta.odd}?'odd':'even'">
	<td th:text="${user.id}"></td>
	<td th:text="${user.username}"></td>
	<td th:text="${user.password}"></td>
	<td th:text="${user.petname}"></td>
</tr>
//th:each="user,sta:${userlist}"
user为每次遍历时的对象
sta 状态变量,他包含下面属性
1.index:当前迭代索引,从0开始。这是索引属性。
2.count:当前迭代索引,从1开始。这是统计属性。
3.size:元素的总量迭代变量。这是大小属性。 
4.current:iter变量为每个迭代。这是目前的财产。 
5.even/odd:是否当前迭代是奇数还是偶数。这些even/odd的布尔属性。  
6.first:是否第一个当前迭代。这是first布尔属性。  
7.last:是否最后一个当前迭代。这是last布尔属性。

可能在实际项目中,我们还需要通过th:each实现一些类似九九乘法表功能,我就在项目中,使用了th:each实现了分页逻辑判断,效果图是这样的

相关代码如下:

//result为一个page对象,拥有的属性如下
	private int allRow;//总记录数
	private int totalPage;//总页数
	private int currentPage;//当前页数
	private int pageSize;//每页的记录数
	private boolean isFirstPage;//是否为当前的第一页
	private boolean isLastPage;//是否为最后一页
	private boolean hasPreviousPage;//是否有前一页
	private boolean hasNaxtPage;//是否有下一页
	private int pageandsize;
	private String keyword;
	private int rows;   // 每页显示的记录数
	private int page; // 当前页
	private int start; // 从第几条记录开始获取
pageNo为当前页

<nav th:if="${#lists.size(cloudCollectionList)}>0" class="row common-page">
	<i class="col-md-5 col-xs-5">共<i th:text="${result.totalPage}"></i>页&nbsp;<i th:text="${result.allRow}"></i>条记录</i>
	<ul class="pagination col-md-7 col-xs-7">
		<li th:if="${pageNo ne 0}" >
			<a style="padding:6px;" th:href="${#httpServletRequest.getContextPath()} +'/cloud/getCloudList/'+${pageNo - 1}+'?isAll='+${isAll}+'&search='+${search}"><span class="pagepre"></span></a>
		</li>
		<th:block th:if="${pageNo gt 4 and pageNo - 4 ne 1}">
			<li><a th:href="${#httpServletRequest.getContextPath()} +'/cloud/getCloudList/0?isAll='+${isAll}+'&search='+${search}">1</a></li>
			<li><a href="javascript:;">...</a></li>
		</th:block>
		<li th:if="${pageNo>4 and pageNo - 4==1}" >
			<a th:href="${#httpServletRequest.getContextPath()} +'/cloud/getCloudList/0?isAll='+${isAll}+'&search='+${search}" title="1">1</a>
		</li>
		<th:block th:if="${pageNo} gt 2">
			<li th:each="val,sta:${#numbers.sequence((pageNo - 3),pageNo)}" th:if="${sta.current} ne 0">
				<a th:href="${#httpServletRequest.getContextPath()}+'/cloud/getCloudList/'+(${sta.current}-1)+'?isAll='+${isAll}+'&search='+${search}" th:title="${sta.current}" th:text="${sta.current}"></a>
			</li>
			<li class="active"><a href="javascript:;" th:text="${pageNo}+1"></a></li>
			<th:block th:if="${pageNo+2 le result.totalPage}">
				<li th:each="val,sta:${#numbers.sequence(pageNo+2,result.totalPage)}" th:if="${sta.count} lt 5 and ${sta.current} ne 0">
					<a th:href="${#httpServletRequest.getContextPath()}+'/cloud/getCloudList/'+(${sta.current}-1)+'?isAll='+${isAll}+'&search='+${search}"  th:title="${sta.current}" th:text="${sta.current}"></a>
				</li>
			</th:block>
		</th:block>
		<th:block th:if="${pageNo} le 2 and ${result.totalPage} gt 0">
			<th:block th:each="val,sta:${#numbers.sequence(0,pageNo)}">
				<li th:if="${sta.current} ne 0"><a th:href="${#httpServletRequest.getContextPath()}+'/cloud/getCloudList/'+(${sta.current}-1)+'?isAll='+${isAll}+'&search='+${search}" th:title="${sta.current}" th:text="${sta.current}"></a></li>
			</th:block>
			<li class="active"><a href="javascript:;" th:text="${pageNo}+1"></a></li>
			<th:block th:if="${pageNo+2 le result.totalPage}">
				<li th:each="val,sta:${#numbers.sequence(pageNo+2,result.totalPage)}" th:if="${sta.count} lt 5 and ${sta.current} ne 0">
					<a th:href="${#httpServletRequest.getContextPath()}+'/cloud/getCloudList/'+(${sta.current}-1)+'?isAll='+${isAll}+'&search='+${search}" th:title="${sta.current}" th:text="${sta.current}"></a>
				</li>
			</th:block>
		</th:block>
		<th:block th:if="${result.totalPage}-${pageNo} gt 6">
			<li><a href="javascript:;">...</a></li>
			<li><a th:href="${#httpServletRequest.getContextPath()}+'/cloud/getCloudList/'+(${result.totalPage}-1)+'?isAll='+${isAll}+'&search='+${search}" th:text="${result.totalPage}" th:title="${result.totalPage}"></a></li>
		</th:block>
		<li th:if="${result.totalPage}-${pageNo} eq 6"><a th:href="${#httpServletRequest.getContextPath()}+'/cloud/getCloudList/'+(${result.totalPage}-1)+'?isAll='+${isAll}+'&search='+${search}"  th:text="${result.totalPage}" th:title="${result.totalPage}"></a></li>
		<li th:if="${pageNo+1} lt ${result.totalPage} and ${result.totalPage} gt 0"><a style="padding:6px;" th:href="${#httpServletRequest.getContextPath()}+'/cloud/getCloudList/'+(${pageNo}+1)+'?isAll='+${isAll}+'&search='+${search}"><span class="pagenxt"></span></a></li>
	</ul>
</nav>

 4.th:src 图片引用

<img alt="" th:src="${#httpServletRequest.getContextPath()}+'/images/wechat/wechat_404.png'">

这里用到了thymeleaf的基础对象#httpServletRequest,thymeleaf还提供了一些内置对象啥的,再这里推荐这篇博文,需要的可以看一下:https://blog.csdn.net/zrk1000/article/details/72667478

本篇博文,我只列举了,我使用过程中造成阻碍的标签,至于其他的,大家可以看其他博主写的博客。如果其中有什么不对的地方,欢迎大家指出。

展开阅读全文

没有更多推荐了,返回首页