使用 jQuery Datatable 实现动态数据加载

本文将介绍如何使用 jQuery Datatable 构造数据列表,并通过后台动态加载数据以提高效率。同时,我们还将学习如何实现排序、分页和搜索等功能。

## 主要步骤

1. 通过后台进行分页

2. 通过后台进行排序

3. 通过后台进行搜索

具体使用方法如下:

### 第1步:构建数据列表及页面显示表格

首先,我们需要构建一个数据列表以及一个用于显示数据的 HTML 表格。以下是一个简单的示例:

```html

ID First Name Last Name Operation

```

表格的构建非常简单,只需定义好表格的 `id` 以及表头即可。

### 第2步:下载 jQuery 和 jQuery Datatable 的 js库

接下来,我们需要下载 jQuery 和 jQuery Datatable 的相关文件。可以从以下链接下载:https://datatables.net/examples/server_side/simple.html。请确保下载最新的 jQuery Datatable 版本,因为它的写法以及参数更加简洁,功能更加多。【注:参数区别会在附录写明】

### 第3步:引入文件到页面中

将下载好的 jQuery 和 jQuery Datatable 文件引入到页面文件中。注意,jQuery 的库一定要在最前面,因为页面加载有顺序,保证后面的扩展库能使用到 jQuery。同时,请按照官方文档的要求引入相应的 CSS 和 JavaScript 文件。

. 编写前端代码。我们需要使用Ajax对后台进行请求,因此在配置datatable时,加上`{ "serverSide": true }`,以确保页面在加载时就请求后台数据,以及每次对datatable进行操作时也是请求后台数据。如果想要添加一些加载效果,可以增加`{ "processing": true }`。

配置请求后台URL:{ "ajax": "load" }

5. 配置数据返回对应的具体列。在Datatable中,属性columns用来配置具体列的属性,包括对应的数据列名、是否支持搜索、是否显示、是否支持排序等。根据上述页面配置,我们可以设置具体的列如下:

```javascript

$(document).ready(function() {

$('#datatable').dataTable({

"processing": true,

"serverSide": true,

"ajax": "load",

"columns": [

{

"data": "id",

"bSortable": false

},

{

"data": "firstName"

},

{

"data": "lastName"

}

]

});

});

```

第一列ID设置为不允许排序。也可以增加不显示的设置: `{ "visible": false }`

6. 对于后台而言,返回的数据需要按照一定的规范。例如,确保返回的数据结构正确、数据类型一致等。这样才能保证前端能够正确地解析和展示数据。

"draw": 2,

"recordsTotal": 11,

"recordsFiltered": 11,

"data": [

{

"id": 1,

"firstName": "Troy",

"lastName": "Young"

},

{

"id": 2,

"firstName": "Alice",

"lastName": "LL"

},

{

"id": 3,

"firstName": "Larry",

"lastName": "Bird"

},

{

"columnDefs": [

{

"targets": [0],

"render": function (data, type, row) {

var editBtn = '修改';

return editBtn;

}

}

]

}

]

}

以下是重构后的代码:

```javascript

$(document).ready(function() {

$( "#datatable" ).dataTable({

"processing": true,

"serverSide": true,

"ajax": "load",

"columns": [

{ "data": "id", "bSortable": false },

{ "data": "firstName" },

{ "data": "lastName" }

],

"columnDefs": [

{

"targets": [3],

"data": "id",

"render": function(data, type, full) {

return "Update";

}

}

]

});

});

```

具体效果图如下:

8. 我们再来看具体如何进行搜索、排序、分页。由于只是为了做 demo ,因此使用最简单的 JDBC+Servlet 的方式来实现。首先我们来看, datatable 给我们在做请求是传递过来的参数:

请求参数如下:

1. draw: 表格的列数,这里为1

2. columns[0][data]: 第一列数据的字段名,这里是 id

3. columns[0][name]: 第一列数据的显示名称,这里是 id

4. columns[0][searchable]: 是否允许对该列进行搜索,这里为 true

5. columns[0][orderable]: 是否允许对该列进行排序,这里为 true

6. columns[0][search][value]: 搜索框中的初始值,这里是 id

7. columns[0][search][regex]: 是否启用正则表达式搜索,这里为 false

8. columns[1][data]: 第二列数据的字段名,这里是 firstName

9. columns[1][name]: 第二列数据的显示名称,这里是 first name

10. columns[1][searchable]: 是否允许对该列进行搜索,这里为 true

11. columns[1][orderable]: 是否允许对该列进行排序,这里为 true

12. columns[1][search][value]: 搜索框中的初始值,这里是 first name

13. columns[1][search][regex]: 是否启用正则表达式搜索,这里为 false

14. columns[2][data]: 第三列数据的字段名,这里是 lastName

15. columns[2][name]: 第三列数据的显示名称,这里是 last name

16. columns[2][searchable]: 是否允许对该列进行搜索,这里为 true

17. columns[2][orderable]: 是否允许对该列进行排序,这里为 true

18. columns[2][search][value]: 搜索框中的初始值,这里是 last name

19. order[0][column]: 需要排序的列的索引,这里为 0(表示第一列)

20. order[0][dir]: 排序方式,ASC | DESC(升序或降序)

21. start: 记录的起始位置,这里为 0

22. length: 每页显示的数据条数,这里为 10

23. search[value]: search 输入框中的值,这里是空字符串("")

以下是根据提供的内容重构的 DAO 层代码,包含排序、搜索和分页功能:

```java

public interface UserDao {

/**

* 根据用户名查询用户信息

* @param username 用户名

* @return 用户信息列表

*/

List findByUsername(String username);

/**

* 根据邮箱查询用户信息

* @param email 邮箱地址

* @return 用户信息列表

*/

List findByEmail(String email);

/**

* 根据手机号查询用户信息

* @param phoneNumber 手机号

* @return 用户信息列表

*/

List findByPhoneNumber(String phoneNumber);

}

```

在上述代码中,我们定义了一个名为 `UserDao` 的接口,该接口包含了三个方法:`findByUsername`、`findByEmail` 和 `findByPhoneNumber`,分别用于根据用户名、邮箱和手机号查询用户信息。这些方法返回一个包含用户信息的列表。

```java

/** * This method includes the search, sort, pagination

* @param pageSize 页面大小

* @param startRecord 起始记录

* @param sortColumn 排序列

* @param sortDir 排序方向(升序或降序)

* @param searchValue 搜索值

* @return 返回结果列表

*/

public List loadDataList(int pageSize, int startRecord, String sortColumn, String sortDir, String searchValue) {

List results = new ArrayList();

StringBuffer sql = new StringBuffer("select * from data");

// for search

String[] columnsName = {"id", "firstName", "lastName"};

boolean searchAble = false;

if (searchValue != null && !"".equals(searchValue)) {

sql.append(" where ");

searchAble = true;

}

if (searchAble) {

StringBuffer temp = new StringBuffer();

for (String column : columnsName) {

temp.append(column + " like '%" + searchValue + "%' or ");

}

sql.append(temp.substring(0, temp.length() - 3));

}

// for order

sql.append(" order by " + sortColumn + " " + sortDir);

// for pagination

sql.append(" limit ?,?");

System.out.println(sql.toString());

try {

stmt = conn.prepareStatement(sql.toString());

stmt.setInt(1, startRecord);

stmt.setInt(2, startRecord + pageSize);

ResultSet rs = stmt.executeQuery();

while (rs.next()) {

Data data = new Data();

data.setId(rs.getInt(1));

data.setFirstName(rs.getString(2));

data.setLastName(rs.getString(3));

results.add(data);

}

} catch (SQLException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return results;

}

```

首先,我们需要创建一个统一的类来封装数据和分页信息。这个类将用于生成 JSON 数据并将其返回给前端。我们可以创建一个名为 `DataVO` 的泛型类,包含以下属性:`draw`(客户端请求次数)、`recordsTotal`(不带条件过滤的总记录数)、`recordsFiltered`(带条件过滤后的总记录数)和 `data`(需要在页面上显示的数据)。此外,我们还需要为这些属性提供 getter 和 setter 方法。

```java

package com.web.vo;

import java.util.List;

public class DataVO {

private int draw; // Client request times

private int recordsTotal; // Total records number without conditions

private int recordsFiltered; // Total records number with conditions

private List data; // The data we should display on the page

// Getter and setter methods

}

```

接下来,我们需要在后端处理数据的分页和排序。这部分代码与之前的代码类似,只需去掉拼接 SQL 以实现分页和排序功能。在处理完数据后,我们可以将其封装到 `DataVO` 类中,并设置相应的属性值。

最后,我们需要实现前后端交互。在这里,我们可以使用最简单的 Servlet 作为示例。Servlet 将从数据库中获取数据,填充到 `DataVO` 对象中,然后将其转换为 JSON 格式并返回给前端。

```java

@WebServlet("/data")

public class DataServlet extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

// 从数据库中获取数据,并将其封装到 DataVO 对象中

DataVO dataVO = new DataVO<>();

// ... populate dataVO with data from database ...

// 将 dataVO 转换为 JSON 格式并返回给前端

response.setContentType("application/json");

response.setCharacterEncoding("UTF-8");

response.getWriter().write(new Gson().toJson(dataVO));

}

}

```

在这个示例中,`YourObject` 是你需要展示在前端的数据对象类型。你需要根据实际情况替换为相应的类型。

以下是重构后的代码:

```java

// 分页参数

int pageSize = 10;

int startRecord = 0;

String size = request.getParameter("length");

if (!"".equals(size) && size != null) {

pageSize = Integer.parseInt(size);

}

String currentRecord = request.getParameter("start");

if (!"".equals(currentRecord) && currentRecord != null) {

startRecord = Integer.parseInt(currentRecord);

}

// 可排序参数

String sortOrder = request.getParameter("order[0][column]");

String sortDir = request.getParameter("order[0][dir]");

System.out.println("sortOrder: " + sortOrder);

System.out.println("sortDir: " + sortDir);

// 搜索参数

String searchValue = request.getParameter("search[value]");

int count = 0;

List results = new ArrayList<>();

count = dao.count();

results = dao.loadDataList(pageSize, startRecord, columnsName[Integer.parseInt(sortOrder)], sortDir, searchValue);

DataVO result = new DataVO<>();

result.setDraw(Integer.parseInt(request.getParameter("draw") == null ? "0" : request.getParameter("draw")) + 1);

result.setData(results);

result.setRecordsTotal(count);

result.setRecordsFiltered(count);

Gson gson = new Gson();

String output = gson.toJson(result);

System.out.println("Output JSON:

" + output);

PrintWriter out = response.getWriter();

out.write(output);

out.flush();

out.close();

```

在较早的 jQuery Datatable 1.10 版本中,必须使用 `sAjaxSource` 进行请求。与当前版本不同,请求数据的格式如下:

```scss

=============== Request Paramerters ================

sEcho: 1

iColumns: 4

sColumns: ,,,

iDisplayStart: 0

iDisplayLength: 10

mDataProp_0: id

sSearch_0: bRegex_0: false

bSearchable_0: true

bSortable_0: false

mDataProp_1: firstName

sSearch_1: bRegex_1: false

bSearchable_1: true

bSortable_1: true

mDataProp_2: lastName

sSearch_2: bRegex_2: false

bSearchable_2: true

bSortable_2: true

mDataProp_3: id

sSearch_3: bRegex_3: false

bSearchable_3: true

bSortable_3: true

sSearch: bRegex: false

iSortCol_0: 0

sSortDir_0: asc

iSortingCols: 1 _: 1399515247114 =============== Request Paramerters ================

```

随着新特性的添加和不断更新,请关注后续版本的使用说明。