Spring Boot整理——Thymeleaf模板(七)

打个广告,帮朋友卖点东西,东西超便宜的哟【衣服鞋子等】,厂家直接出货,绝对低于市场价!!! 一般都比市场价便宜3—7折【都是牌子货】,如果您感兴趣,可以扫描屏幕下方的二维码,感谢关注!!!

微信

一、基本介绍

        Thymeleaf是一个Java库。它是一个XML / XHTML / HTML5模板引擎,能够应用于转换模板文件,以显示您的应用程序产生的数据和文本。它尤其适合于基于XHTML / HTML5的web服务应用程序,同时它可以处理任何XML文件,作为web或独立的应用程序。

        Thymeleaf的主要目的是提供一个优雅和格式良好的方式创建模板。为了实现这一目标,它把预定义的逻辑放在XML的标记和属性上,而不是显式放在XML标记的内容上。依靠智能缓存去解析文件,致使其执行期间的I / O操作达到了最少数量,因此其处理的模板的能力实非常快速的。

        Thymeleaf的标准方言为:

<span th:text="..."><!--需要引入命名空间-->
<span data-th-text="..."><!--可以不引入命名空间-->

二、语法介绍

1、表达式

        Thymeleaf支持的表达式有ognl表达式和springEL表达式。

变量表达式:${...}

<span th:text="${book.author.name}">

消息表达式:#{...} 

        将key映射成对应的value,也称为文本外部化、国际化或i18n。

<table>
    ...
    <th th:text="#{header.address.city}">...</th>
    <th th:text="#{header.address.country}">...</th>
    ...
</table>

选择表达式:*{...}

        它们是在当前选择的对象而不是整个上下文变量映射上执行,效率上会快很多。

<div th:object="${book}">
    ...
    <span th:text="*{title}">...</span><!--取book的title的属性-->
    ...
</div>

链接表达式:@{...}

        链接表达式可以是相对的,在这种情况下,应用程序上下文将不会作为URL的前缀:

<a th:href="@{../documents/report}">...</a>

也可以是服务器相对(同样,没有应用程序上下文前缀),

<a th:href="@{~/contents/main}">...</a>

和协议相对(就像绝对URL,但是浏览器将使用在显示的页面中使用的相同的HTTP或HTTPS协议),

<a th:href="@{//static.mycompany.com/res/initial}">...</a>

当然,Link表达式可以是绝对的:

<a th:href="@{http://www.mycompany.com/main}">...</a>  

分段表达式:th:insert(整个片段插入div)或th:replace(把自己替换掉)

<!--页面一-->
<body>
    <div th:fragment="copy" id="copyId"><!--自定义片段,如页面头等-->
        ...
    </div>
<body>
​
<!--页面二-->
<div th:insert="~{footer :: copy}"></div><!--表示将copy的内容插入到这里来,重用-->
<div th:insert="~{footer :: #copyId}"></div><!--也可以不用fragment,直接根据id-->

2、字面量

文本

<span th:text="${book.author.name}">

布尔

<div th:if="${user.isAdmin()} == false">...

无操作

<span th:text="${user.name}? : _">no user name</span><!--即如果user.name不存在就显示“no user name”-->

3、设置属性值

设置任意属性值 th:attr:

<form action="subscribe.html" th:attr="action=@{/subscribe}">
    <input type="submit" th:attr="value=#{subscribe.submit}"/>
</form>

设置指定属性:

<form action="subscribe.html" th:action="@{/subscribe}">
    <input type="submit" th:value="#{subscribe.submit}"/>
</form>

4、迭代器

基本的迭代 th:each :

<li th:each="book : ${books}" th:text = "${book.title}">En las del Sar</li>

状态变量:index、count、size、current、even(奇数)/odd(偶数)、first、last

下面是一个例子

  <table>
    <tr>
      <th>NAME</th>
      <th>PRICE</th>
      <th>IN STOCK</th>
    </tr>
    <tr th:each="prod,iterStat: ${prods}" th:class="${iterStat.odd}? 'odd'">
      <td th:text="${prod.name}">Onions</td>
      <td th:text="${prod.price}">2.41</td>
      <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
    </tr>
  </table>

5、条件语句

if/unless

        Thymeleaf中使用th:if和th:unless属性进行条件判断,下面的例子中,标签只有在th:if中条件成立时才显示: 

<a th:href="@{/login}" th:if=${session.user != null}>Login</a>

th:unless于th:if恰好相反,只有表达式中的条件不成立,才会显示其内容。

Switch

Thymeleaf同样支持多路选择Switch结构:

<div th:switch="${user.role}">
  <p th:case="'admin'">User is an administrator</p>
  <p th:case="#{roles.manager}">User is a manager</p>
</div>

默认属性default可以用*表示: 

<div th:switch="${user.role}">
  <p th:case="'admin'">User is an administrator</p>
  <p th:case="#{roles.manager}">User is a manager</p>
  <p th:case="*">User is some other thing</p>
</div>

6、注释

解析器级别注释:静态时候会被显示,当模板执行(Thymeleaf解析)时,这些会被注释

<!--/*-->
    <div>
        you can see me !
    </div>
<!--*/-->

原型注释:当模板静态打开时不显示,当模板执行(Thymeleaf解析)时,这些被注释内容将会显示,和上面相反:

<span>hello</span>
<!--/*/
    <div th:text="${...}">
        ...
    </div>
/*/-->
<span>goodbye</span>

7、内联

        [[...]]和[(...)]分别对应于th:text和th:utext

<p>the message is [(${msg})]</p>
===》
<p>the message is <b>great</b></p>
​
<p>the message is [[${msg}]]</p>
===》
<p>the message is &lt; b &gt; great &lt; /b &gt;</p>

8、内置对象

1.基本对象

        ctx,对象继承org.thymeleaf.context.IContext或者org.thymeleaf.context.IWebContext,取决于当前环境是不是web环境。如果程序集成了spring,那么将会是org.thymeleaf.spring[3|4].context.SpringWebContext。

/*
* ======================================================================
* See javadoc API for class org.thymeleaf.context.IContext
* ======================================================================
*/
${#ctx.locale}
${#ctx.variables}
/*
* ======================================================================
* See javadoc API for class org.thymeleaf.context.IWebContext
* ======================================================================
*/
${#ctx.applicationAttributes}
${#ctx.httpServletRequest}
${#ctx.httpServletResponse}
${#ctx.httpSession}
${#ctx.requestAttributes}
${#ctx.requestParameters}
${#ctx.servletContext}
${#ctx.sessionAttributes}

  locale,java.util.Locale对象的访问.  

  vars,org.thymeleaf.context的实例。访问VariablesMap所有上下文中的变量(包含本笃和ctx.variables中的)。

/*
* ======================================================================
* See javadoc API for class org.thymeleaf.context.VariablesMap
* ======================================================================
*/
${#vars.get('foo')}
${#vars.containsKey('foo')}
${#vars.size()}

2.web环境中访问request/session等属性

        当在web环境中使用Thymeleaf,我们可以使用一系列的快捷方式访问请求的参数,会话和应用程序的属性.

param,获取请求的参数.

/*
* ============================================================================
* See javadoc API for class org.thymeleaf.context.WebRequestParamsVariablesMap
* ============================================================================
*/
${param.foo} // Retrieves a String[] with the values of request parameter 'foo'
${param.size()}
${param.isEmpty()}
${param.containsKey('foo')}

session,访问session属性。

/*
* ======================================================================
* See javadoc API for class org.thymeleaf.context.WebSessionVariablesMap
* ======================================================================
*/
${session.foo} // Retrieves the session atttribute 'foo'
${session.size()}
${session.isEmpty()}
${session.containsKey('foo')}

application,获取应用程序/ servlet上下文属性。

/*
* =============================================================================
* See javadoc API for class org.thymeleaf.context.WebServletContextVariablesMap
* =============================================================================
*/
${application.foo} // Retrieves the ServletContext atttribute 'foo'
${application.size()}
${application.isEmpty()}
${application.containsKey('foo')}

3.web环境对象

        httpServletRequest :javax.servlet.http.HttpServletRequest对象实例。

${#httpServletRequest.getAttribute('foo')}
${#httpServletRequest.getParameter('foo')}
${#httpServletRequest.getContextPath()}
${#httpServletRequest.getRequestName()}
...

        httpSession:javax.servlet.http.HttpSession实例。

${#httpSession.getAttribute('foo')}
${#httpSession.id}
${#httpSession.lastAccessedTime}
...

4.spring环境对象

        themes : 提供和“ spring:theme JSP tag.”同样的功能。

${#themes.code('foo')}
​
<!--直接访问spring注册对象-->
<div th:text="${@authService.getUserName()}">...</div>

三、项目实战

1、基本搭建

        我们在这里创建一个包含用户增删改查功能的项目,这里采用Gradle来构建项目,其中build.gradle配置如下:

// buildscript 代码块中脚本优先执行
buildscript {
​
    // ext 用于定义动态属性
    ext {
        springBootVersion = '1.5.2.RELEASE'
    }

    // 自定义  Thymeleaf 和 Thymeleaf Layout Dialect 的版本
    ext['thymeleaf.version'] = '3.0.3.RELEASE'
    ext['thymeleaf-layout-dialect.version'] = '2.2.0'

    // 使用了 Maven 的中央仓库(你也可以指定其他仓库)
    repositories {
        //mavenCentral()
        maven {
            url 'http://maven.aliyun.com/nexus/content/groups/public/'
        }
    }

    // 依赖关系
    dependencies {
        // classpath 声明说明了在执行其余的脚本时,ClassLoader 可以使用这些依赖项
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}
​
// 使用插件
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
​
// 打包的类型为 jar,并指定了生成的打包的文件名称和版本
jar {
    baseName = 'thymeleaf-in-action'
    version = '1.0.0'
}
​
// 指定编译 .java 文件的 JDK 版本
sourceCompatibility = 1.8
​
// 默认使用了 Maven 的中央仓库。这里改用自定义的镜像库
repositories {
    //mavenCentral()
    maven {
        url 'http://maven.aliyun.com/nexus/content/groups/public/'
    }
}
​
// 依赖关系
dependencies {
    // 该依赖对于编译发行是必须的
    compile('org.springframework.boot:spring-boot-starter-web')

    // 添加 Thymeleaf 的依赖
    compile('org.springframework.boot:spring-boot-starter-thymeleaf')
​
    // 该依赖对于编译测试是必须的,默认包含编译产品依赖和编译时依
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

​然后配置application.properties内容如下:

# THYMELEAF 
spring.thymeleaf.encoding=UTF-8
# 热部署静态文件
spring.thymeleaf.cache=false
# 使用HTML5标准
spring.thymeleaf.mode=HTML5

2、后台逻辑

1.实体

public class User {
    private long id; // 用户的唯一标识
    private String name;
    private int age;
}

2.业务逻辑

/**
 * 用户仓库.
 */
public interface UserRepository {
    /**
     * 新增或者修改用户
     * @param user
     * @return
     */
    User saveOrUpateUser(User user);

    /**
     * 删除用户
     * @param id
     */
    void deleteUser(Long id);

    /**
     * 根据用户id获取用户
     * @param id
     * @return
     */
    User getUserById(Long id);

    /**
     * 获取所有用户的列表
     * @return
     */
    List<User> listUser();
}

其中实现类如下:

@Repository
public class UserRepositoryImpl implements UserRepository {

    private static AtomicLong counter = new AtomicLong();
​
    private final ConcurrentMap<Long, User> userMap = new ConcurrentHashMap<Long, User>();

    public UserRepositoryImpl(){
        User user = new User();
        user.setAge(30);
        user.setName("Way Lau");
        this.saveOrUpateUser(user);
    }

    @Override
    public User saveOrUpateUser(User user) {
        Long id = user.getId();
        if (id <= 0) {
            id = counter.incrementAndGet();
            user.setId(id);
        }
        this.userMap.put(id, user);
        return user;
    }
​
    @Override
    public void deleteUser(Long id) {
        this.userMap.remove(id);
    }
​
    @Override
    public User getUserById(Long id) {
        return this.userMap.get(id);
    }
​
    @Override
    public List<User> listUser() {
        return new ArrayList<User>(this.userMap.values());
    }
​
}

3.控制层

/**
 * 用户控制器.
 */
@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired 
    private UserRepository userRepository;
​
    /**
     * 从 用户存储库 获取用户列表
     * @return
     */
    private List<User> getUserlist() {
        return userRepository.listUser();
    }
​
    /**
     * 查询所用用户
     * @return
     */
    @GetMapping
    public ModelAndView list(Model model) {
        model.addAttribute("userList", getUserlist());
        model.addAttribute("title", "用户管理");
        return new ModelAndView("users/list", "userModel", model);
    }

    /**
     * 根据id查询用户
     * @param message
     * @return
     */
    @GetMapping("{id}")
    public ModelAndView view(@PathVariable("id") Long id, Model model) {
        User user = userRepository.getUserById(id);
        model.addAttribute("user", user);
        model.addAttribute("title", "查看用户");
        return new ModelAndView("users/view", "userModel", model);
    }
​
    /**
     * 获取 form 表单页面
     * @param user
     * @return
     */
    @GetMapping("/form")
    public ModelAndView createForm(Model model) {
        model.addAttribute("user", new User());
        model.addAttribute("title", "创建用户");
        return new ModelAndView("users/form", "userModel", model);
    }
​
    /**
     * 新建用户
     * @param user
     * @param result
     * @param redirect
     * @return
     */
    @PostMapping
    public ModelAndView create(User user) {
        user = userRepository.saveOrUpateUser(user);
        return new ModelAndView("redirect:/users");
    }
​
    /**
     * 删除用户
     * @param id
     * @return
     */
    @GetMapping(value = "delete/{id}")
    public ModelAndView delete(@PathVariable("id") Long id, Model model) {
        userRepository.deleteUser(id);

        model.addAttribute("userList", getUserlist());
        model.addAttribute("title", "删除用户");
        return new ModelAndView("users/list", "userModel", model);
    }
​
    /**
     * 修改用户
     * @param user
     * @return
     */
    @GetMapping(value = "modify/{id}")
    public ModelAndView modifyForm(@PathVariable("id") Long id, Model model) {
        User user = userRepository.getUserById(id);

        model.addAttribute("user", user);
        model.addAttribute("title", "修改用户");
        return new ModelAndView("users/form", "userModel", model);
    }
}

3、前台页面

1.公共页脚

header.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf in action</title>
</head>
<body>
<div data-th-fragment="header">
    <h1>Thymeleaf in action</h1>
    <a href="/users">首页</a>
</div>
</body>
</html>

footer.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Thymeleaf in action</title>
</head>
<body>
<div data-th-fragment="footer">
    <a href="https://waylau.com">Welcome to waylau.com</a>
</div>
</body>
</html>

2.功能页面

list.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <title th:text="${userModel.title}">welcome</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}">...</div>
<h3 th:text="${userModel.title}">Welcome to waylau.com</h3>
<div>
    <a href="/users/form.html">创建用户</a>
</div>
<table border="1">
    <thead>
    <tr>
        <td>ID</td>
        <td>Age</td>
        <td>Name</td>
    </tr>
    </thead>
    <tbody>
    <tr th:if="${userModel.userList.size()} eq 0">
        <td colspan="3">没有用户信息!!</td>
    </tr>
    <tr th:each="user : ${userModel.userList}">
        <td th:text="${user.id}">1</td>
        <td th:text="${user.age}">11</td>
        <td><a href="view.html" th:href="@{'/users/' + ${user.id}}"
               th:text="${user.name}">waylau</a></td>
    </tr>
    </tbody>
</table>
<div th:replace="~{fragments/footer :: footer}">...</div>
</body>
</html>

form.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <title th:text="${userModel.title}">users : View</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}">...</div>
<h3 th:text="${userModel.title}">Welcome to waylau.com</h3>
<div>
    <a href="/users">返回主页</a>
</div>
<form action="/users" method="POST" th:object="${userModel.user}">
    <input type="hidden" name="id" th:value="*{id}">
    名称:<br>
    <input type="text" name="name" th:value="*{name}">
    <br>
    年龄:<br>
    <input type="text" name="age" th:value="*{age}">
    <input type="submit" value="提交">
</form>
<div th:replace="~{fragments/footer :: footer}">...</div>
</body>
</html>

view.html

<html xmlns:th="http://www.thymeleaf.org"
      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
    <title th:text="${userModel.title}">users : View</title>
</head>
<body>
<div th:replace="~{fragments/header :: header}">...</div>
<h3 th:text="${userModel.title}">Welcome to waylau.com</h3>
<div>
    <a href="/users">返回主页</a>
</div>
<div>
    <p><strong>ID:</strong><span id="id" th:text="${userModel.user.id}">123</span></p>
    <p><strong>Name:</strong><span id="name" th:text="${userModel.user.name}">waylau</span></p>
    <p><strong>Age:</strong><span id="age" th:text="${userModel.user.age}">30</span></p>
</div>
​
<div>
    <a th:href="@{'/users/delete/' + ${userModel.user.id}}">删除 </a>
    | <a th:href="@{'/users/modify/' + ${userModel.user.id}}">修改</a>
</div>
<div th:replace="~{fragments/footer :: footer}">...</div>
</body>
</html>

下面是项目结构图:

4、扩展

1.异步加载

        在Thymeleaf中进行页面分页操作时,在翻页操作中,我们显然要通过异步方式加载数据,下面我们一分页操作来看其异步加载操作,首先其html页面如下:

我们对应的js代码为

然后后台代码如下:

最后附上分页的脚步如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
​
<nav data-th-fragment="page" data-th-if="${page.totalPages gt 0}" data-th-object="${page}">

    <!-- 处理页数小于等于7 的情况 -->
    <ul class="pagination" data-th-if="${page.totalPages le 7}" >
        <!-- 总记录数 -->
        <li class="tbpage-total-elements disabled">共[[${page.totalElements}]]条</li>

        <!-- 页面大小 -->
        <select class="custom-select tbpage-size" data-th-attr="pageIndex=${page.number}">
            <option data-th-each="i : ${#arrays.toIntegerArray({5,10,40,100})}" data-th-value="${i}" 
                 data-th-selected="${i eq page.size}" data-th-text="${i}"></option>
        </select>

        <!-- 上一页 -->
        <li class="page-item" data-th-classappend="*{first} ? 'disabled' : ''">
            <a href="javascript:void(0);" class="page-link tbpage-item" data-th-attr="pageIndex=${page.number} - 1" aria-label="Previous">
                <span aria-hidden="true">«</span>
            </a>
        </li>

        <!-- 迭代生成页码 -->
        <li class="page-item" data-th-each="i : ${#numbers.sequence(1, page.totalPages)}" 
            data-th-classappend="${(page.number + 1) eq i} ? 'active' : ''" >
            <a class="page-link tbpage-item" data-th-attr="pageIndex=${i} - 1" href="javascript:void(0);">
                 <span data-th-text="${i}"></span>
            </a>
        </li>

        <!-- 下一页 -->
        <li class="page-item" data-th-classappend="*{last} ? 'disabled' : ''">
            <a href="javascript:void(0);" class="page-link tbpage-item" data-th-attr="pageIndex=${page.number} + 1" aria-label="Next">
                <span aria-hidden="true">»</span>
            </a>
        </li>
    </ul>

    <!-- 处理页数大于7 的情况 -->    
    <ul class="pagination" data-th-if="${page.totalPages gt 7}" >
        <!-- 总记录数 -->
        <li class="tbpage-total-elements disabled">共[[${page.totalElements}]]条</li>

        <!-- 页面大小 -->
        <select class="custom-select tbpage-size" data-th-attr="pageIndex=${page.number}">
            <option data-th-each="i : ${#arrays.toIntegerArray({5,10,40,100})}" data-th-value="${i}" 
                 data-th-selected="${i eq page.size}" data-th-text="${i}"></option>
        </select>

        <!-- 上一页 -->
        <li class="page-item" data-th-classappend="*{first} ? 'disabled' : ''">
            <a href="javascript:void(0);" class="page-link tbpage-item" data-th-attr="pageIndex=${page.number} - 1" aria-label="Previous">
                <span aria-hidden="true">«</span>
            </a>
        </li>

        <!-- 首页 -->
        <li class="page-item" data-th-classappend="${(page.number + 1) eq 1} ? 'active' : ''" >
            <a href="javascript:void(0);" class="page-link tbpage-item" data-th-attr="pageIndex=0">1</a>
        </li>


        <!-- 当前页面小于等于4 -->
        <li class="page-item" data-th-if="${(page.number + 1) le 4}" data-th-each="i : ${#numbers.sequence(2,5)}" 
            data-th-classappend="${(page.number + 1) eq i} ? 'active' : ''" >
            <a class="page-link tbpage-item" href="javascript:void(0);" data-th-attr="pageIndex=${i} - 1">
                <span data-th-text="${i}"></span>
            </a>
        </li>

        <li class="page-item disabled" data-th-if="${(page.number + 1) le 4}">
            <a href="javascript:void(0);" class="page-link tbpage-item">
                <span aria-hidden="true">...</span>
            </a>
        </li>

        <!-- 最后一页与当前页面之差,小于等于3 -->
        <li class="page-item disabled" data-th-if="${(page.totalPages-(page.number + 1)) le 3}">
            <a href="javascript:void(0);" class="page-link tbpage-item">
                <span aria-hidden="true">...</span>
            </a>
        </li>  
        <li class="page-item" data-th-if="${(page.totalPages-(page.number + 1)) le 3}" data-th-each="i : ${#numbers.sequence(page.totalPages-4, page.totalPages-1)}" 
            data-th-classappend="${(page.number + 1) eq i} ? 'active' : ''" >
            <a class="page-link tbpage-item" href="javascript:void(0);" data-th-attr="pageIndex=${i} - 1">
                <span data-th-text="${i}"></span>
           </a>
        </li>

         <!-- 最后一页与当前页面之差大于3,且  当前页面大于4-->

        <li class="page-item disabled" data-th-if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}">
            <a href="javascript:void(0);" class="page-link tbpage-item">
                <span aria-hidden="true">...</span>
            </a>
        </li> 
        <li class="page-item" data-th-if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}" >
            <a href="javascript:void(0);" class="page-link tbpage-item" data-th-attr="pageIndex=${page.number}">[[${page.number}]]</a>
        </li>
        <li class="page-item active" data-th-if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}">
            <a href="javascript:void(0);" class="page-link tbpage-item" data-th-attr="pageIndex=${page.number} + 1">[[${page.number + 1}]]</a>
        </li>
        <li class="page-item" data-th-if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}">
            <a href="javascript:void(0);" class="page-link tbpage-item" data-th-attr="pageIndex=${page.number} + 2">[[${page.number + 2}]]</a>
        </li>

        <li class="page-item disabled"  data-th-if="${((page.number + 1) gt 4) && ((page.totalPages-(page.number + 1)) gt 3 )}">
            <a href="javascript:void(0);" class="page-link tbpage-item">
                <span aria-hidden="true">...</span>
            </a>
        </li>

        <!-- 最后一页 -->
        <li class="page-item" data-th-classappend="${(page.number + 1) eq page.totalPages} ? 'active' : ''" >
            <a href="javascript:void(0);" class="page-link tbpage-item" data-th-attr="pageIndex=${page.totalPages} - 1">[[${page.totalPages}]]</a>
        </li>

        <!-- 下一页 -->
        <li class="page-item" data-th-classappend="*{last} ? 'disabled' : ''">
            <a href="javascript:void(0);" class="page-link tbpage-item" data-th-attr="pageIndex=${page.number} + 1" aria-label="Next">
                <span aria-hidden="true">»</span>
            </a>
        </li>
    </ul>


</nav>
​
</body>
</html>

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

盡盡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值