再写树型列表
- HTML标签的选择
- th:block的使用
以前用jQuery写过一个树型列表,当时选择采用jQuery或者说javascript实现的原因是可以动态获取数据,实现无限层级。现在又要用到这个东西,发现一个问题:其实大多数时候数据并不多,完全可以一次性加载,动态加载的必要性并不高。至于无限层级也不是使用客户端实现的理由,因为使用模板同样可以递归调用,同样能根据数据实现无限层级。至少现在使用的thymeleaf模板是支持的。所以就重写了一个,有新的心得如下:
HTML标签的选择
以前没有HTML5的时候,用html标签很随意,所以基本上都是用div来包装,现在仍然是用div,但想发不一样。按HTML5建议,应该尽量使用符合语义的标签,这种列表的话当然应该用ul或ol,并且,浏览器的用户代理样式表还会自动给予缩进,本来是最合适的。但是,如果想要替换前导符并且实现点击前导符而展开或收缩的功能的话,就只能用图形按钮实现前导符,这个时候要把按钮改为inline,还得要用div包装起来使得前导符和节点在一行。那还不如直接用div。如果直接用行内元素a当按钮,就要在事件处理程序中阻止其默认行为,这种用法很让人费解,还不如牺牲语义直接用div。另外,即使坚持用ul、ol,也还要把默认的缩进去掉,因为用list-style: none;去掉前导符号,自己加的前导符并不能代替那个位置,所以总体上有一个缩进,不太美观。用CSS去掉默认缩进当然也行,但如果直接用div就没这么多考虑的。所以,综合起来还是继续用div。
th:block的使用
以前没用过thymeleaf的唯一的标签(不是属性),即使是用th:each也是把其他th属性直接写后面。但现在需要用到模块引用就不能这样了。一开始是这样写的
<div class="tree" th:with="nodedata=${tree}"><div th:fragment="treenode(nodedata)"><button type="button" th:if="${not #lists.isEmpty(nodedata.subordinate)}"><img th:src="@{/resources/images/chevron-right.svg}" width="16px" height="16px"></button><div th:text="${nodedata.name}" style="display:inline-block"></div><div th:if="${not #lists.isEmpty(nodedata.subordinate)}"><div th:each="child:${nodedata.subordinate}" th:replace="~{::treenode(${child})}"></div></div></div>
</div>
然后报空对像错误,查了很久才发现,thymeleaf的属性是有优先级的,而th:include和th:replace的优先级最高,th:each其次。以前一直把th:each与其他属性一起用没有发现,现在用到片断包含了,它就先替换了这个片断,所以th:each定义的循环变量就没有了,传的参数就成了null。这里即使是把th:replace换成th:include也不行,原因就是th:include优先级最高,先执行,这时候传的参数是空就已经错了,就算th:each仍然起作用,它会再次执行include也没用,之前就已经出错了。这时就需要用到th:block这个元素,把each放在外面。
<div class="tree" th:with="nodedata=${tree}"><div th:fragment="treenode(nodedata)"><button type="button" th:if="${not #lists.isEmpty(nodedata.subordinate)}"><img th:src="@{/resources/images/chevron-right.svg}" width="16px" height="16px"></button><div th:text="${nodedata.name}" style="display:inline-block"></div><div th:if="${not #lists.isEmpty(nodedata.subordinate)}"><th:block th:each="child:${nodedata.subordinate}"><div th:replace="~{::treenode(${child})}"></div></th:block></div></div>
</div>
其他相关的CSS、JavaScript变化、难度不大,不值得记录,就不粘出来了。