在前一篇,miniui datagrid 的客户端分页处置惩罚方案 中留下了一个题目:假如前三页只须要加载一次数据,采纳客户端分页,以后的每一页都依然从服务器猎取,应当怎么办?
如今就来革新 ClientPagination
,让它完成这个功用。不过在此之前须要先处置惩罚上个版本中存在的一个题目:destroy()
并没有完全恢回复有的 datagrid 对象,由于忘了在 destroy()
中恢复 this._datagrid
的 load
和 setData
函数。
修复一个主要的 BUG
很轻易想到下面的代码,不过下面这个代码是个毛病的完成
destroy() {
// 毛病的完成
METHODS.forEach(name => {
this._datagrid[name] = this._origin[name];
});
// ....
}
别忘了 this._origin
中保留的每一个函数都是经由过程原函数 bind()
而来,所以实在已不是原函数了。另外,也很轻易想到 miniui 的 datagrid 多半是类完成,本来的 load()
和 setData()
应当来源于原型。所以准确的处置惩罚办法是
// in destroy's body
METHODS.forEach(name => {
delete this._datagrid[name];
});
试验一下就可以证实它的准确性。
革新 ClientPagination
修正 beforeload 事宜处置惩罚
本来在 beforeload
事宜中直接设置了 event.cancel = true
来防止长途加载,但如今状况发生了变化,只须要在页码小于3(miniui 的 pageIndex
是从 0 最先)防止长途加载,大于即是 3 的时刻依然须要从服务器猎取页面数据,所以
const pageIndex = e.data.pageIndex;
if (pageIndex < 3) {
e.cancel = true;
} else {
// 直接返回,不须要经由过程 setPageData() 来设置页面数据
return;
}
接下来该干啥
接下来另有一些细节须要处置惩罚。
起首就是 setData
中没有运用数据的 total
值,由于本来纯客户端分页的时刻,数据总行数就是 total
值,但如今不一样了,设置的数据不一定是一切数据,所以须要先搜检 total
,假如没有 total
再运用 rows.length
替代。
setData(data) {
const rows = Array.isArray(data)
? data
: (data.data || []);
this._data = rows;
this._total = data.total || rows.length;
this.setPageData(this._datagrid.getPageIndex(), this._datagrid.getPageSize());
}
响应的,还须要在 setPageData()
里修正一个 setTotalCount()
的实参
grid.setTotalCount(this._total);
搞定!
源代码
ClientPagination mini_clientpagination.js
const METHODS = ["setData", "load"];
class ClientPagination {
static wrap(datagrid) {
return new ClientPagination(datagrid);
}
constructor(datagrid) {
this._datagrid = datagrid;
this._origin = {};
this.setup();
}
setup() {
const grid = this._datagrid;
const origin = this._origin = {};
METHODS.forEach(name => {
// 绑定到原对象的原要领
origin[name] = grid[name].bind(grid);
// 替换为本类中定义的新要领
grid[name] = this[name].bind(this);
});
// 暂存事宜处置惩罚函数,以便背面注销
this._onBeforeLoad = this.onBeforeLoad.bind(this);
grid.on("beforeload", this._onBeforeLoad);
}
destroy() {
// 恢回复要领(来自 datagrid 类的 prototype)
// 只须要删除附加到对象上的同名要领即可
METHODS.forEach(name => {
delete this._datagrid[name];
});
this._origin = {};
this._datagrid.un("beforeload", this._onBeforeLoad);
this._datagrid = null;
}
onBeforeLoad(e) {
// 依据官方的处置惩罚方案而来
const pageIndex = e.data.pageIndex;
if (pageIndex < 3) {
e.cancel = true;
} else {
// NOTE 一般来说不须要修正 url,直接经由过程 pageIndex 参数即可从背景猎取差别页的数据
// 这里由于是用的静态 JSON 数据,所以须要修正 url
e.url = `data/page${pageIndex}.json`;
return;
}
let pageSize = e.data.pageSize;
this.setPageData(pageIndex, pageSize);
}
load(params, success, fail) {
const grid = this._datagrid;
const pageIndex = grid.getPageIndex();
const url = grid.getUrl();
params = $.extend(pageIndex < 3
? {}
: { pageIndex: pageIndex, pageSize: grid.getPageSize() },
params);
const settings = {
type: "get",
dataType: "json",
data: params
};
$.ajax(url, settings)
.then(data => {
this.setData(data);
if (typeof success === "function") {
success(data);
}
}, () => {
if (typeof fail === "function") {
fail();
}
});
}
setData(data) {
const rows = Array.isArray(data)
? data
: (data.data || []);
this._data = rows;
this._total = data.total || rows.length;
this.setPageData(this._datagrid.getPageIndex(), this._datagrid.getPageSize());
}
setPageData(pageIndex, pageSize) {
const allData = this._data;
let start = pageIndex * pageSize;
if (start >= allData.length) {
start = 0;
pageIndex = 0;
}
const end = Math.min(start + pageSize, allData.length);
const pageData = [];
for (let i = start; i < end; i++) {
pageData.push(allData[i]);
}
const grid = this._datagrid;
grid.setTotalCount(this._total);
grid.setPageIndex(pageIndex);
grid.setPageSize(pageSize);
this._origin.setData(pageData);
}
}
测试页面 index.html
<!DOCTYPE html />
<html>
<head>
<title>Client Pagination</title>
<link href="miniui/themes/default/miniui.css" rel="stylesheet" type="text/css" />
<style type="text/css">
body {
margin: 0;
padding: 5px;
}
</style>
</head>
<body>
<div class="mini-fit">
<div class="mini-datagrid" id="grid" pageSize="6" url="data/all.json" style="height: 100%">
<div property="columns">
<div type="indexcolumn"></div>
<div type="checkboxcolumn" width="32"></div>
<div field="order" width="60">序号</div>
<div field="name" width="80">称号</div>
<div field="autofit" width="auto"></div>
</div>
</div>
</div>
<script src="jquery-1.6.2.min.js"></script>
<script src="miniui/miniui.js"></script>
<script src="mini_clientpagination.js"></script>
<script>
mini.parse();
const grid = mini.get("grid");
ClientPagination.wrap(grid);
grid.load();
</script>
</body>
</html>
固然另有 data 目录下的数据源 all.json
和 page3.json
- all.json 中是前3页的数据
- page3.json 中是第4页的数据
数据构造(仅构造
{
"data": [],
"total": 50
}
个中 data
的每一项构造
{
"order": 1108,
"name": "bridge"
}
完全的测试数据就本身拼吧,固然最好是照样用服务端数据,经由过程参数来返回差别的数据行。
我懒,懒得为了个试验还去写服务端