Closed xianzou closed 4 years ago
分页需要自己做,indexedDB 没有分页的概念。 有两种方案:1. 全部 select 出来之后做分片,这样可以做缓存;2. 使用游标遍历 store,取出一定数量之后就结束遍历,这样可以减少运行时内存消耗。
谢谢,全部 select 出来之后做分片,这样可以前端进行分页,然后可以做缓存,但是不足之处就是数据量大的时候,性能肯定损耗很大; 如果是用游标的话,如何带上参数和查询条件呢~
游标就是为了遍历,没有参数,在遍历过程中自己决定当前这个 value 要不要加入到你最后输出的结果中。
你可以用 iterate 来做这个遍历 https://github.com/tangshuang/indb#iterate
谢谢你,我已经有思路了,不过我看到迭代iterate用的也是cursor,不过并不可以传递ranage,如果做分页ranage还是比较有用处的;
你好,我有写一个方法,用来进行处理带条件分页的场景,传入页数获取总页数和分页信息,我不知道这样做是不是合理,如果有空可以帮忙看下嘛,谢谢?
conditions是查询条件,如果没有传入查询条件,则通过
db.count()
获取总页数,通过索引index(自增)来获取值的范围;如果是有条件的查询的话,目前的做法是通过油标去遍历所有的项,然后根据页数来判断是否可以存储到数组中,总页数也是遍历所有的数组
//创建一个迭代器
function iterateor(fn, pageInfo = {}) {
const {
indbSocurse,
index,
currentPage = 1,
conditions = [],
pageSize,
pageStart = 1,
pageEnd = 10
} = pageInfo;
let range = null;
// 没有查询条件
if (!conditions.length) {
range = IDBKeyRange.bound(
pageStart,
pageEnd,
false,
false
);
}
return new Promise((resolve, reject) => {
indbSocurse.cursor({
writable: false,
direction: "next",
index: index,
range: range,
onTouch: (cursor, owner) => {
const next = () => cursor.continue();
const stop = () => {
owner.transaction.abort();
resolve();
};
fn(cursor, next, stop);
},
onDone: () => {
resolve();
},
onError: e => {
reject(e);
}
});
});
}
/****
* function ==> 获取列表信息
* 参数解释
* pageSize 一页多少条 number
* conditions 条件 Array [{age:18},{name:'xxx'}] 注意 如果是string类型的使用indexOf查找,否则使用 ===
* indbSocurse indexdb数组源 示例:const indbSocurse = idb.use("students");
* index 索引列表 String类型 index在indexeddb里面的值必须为number类型,设置成自增长
* currentPage 当前第几页
* return {
* total,
* pageSize,
* pageNumber,
* data,
* currentPage
* }
*
*/
export const queryList = async ({
indbSocurse = {},
conditions = [],
pageSize = 10,
index = "id",
currentPage = 1
}) => {
// 判断indbSocurse是不是正确的对象
if (!indbSocurse.db) {
throw Error("indbSocurse必须是一个idb实例化对象");
}
const data = [];
let total = 0;
// 计算当前页的开始和结束
const pageStart = (currentPage - 1) * pageSize + 1;
const pageEnd = currentPage * pageSize;
await iterateor(
(cursor, next, stop) => {
//判断是否符合条件
// 没有查询条件
if (!conditions.length) {
data.push(cursor.value);
} else {
let isMeet = false;
for (let row of conditions) {
if (typeof row[Object.keys(row)] === "string") {
isMeet =
cursor.value[Object.keys(row)].indexOf(row[Object.keys(row)]) >
-1;
} else {
isMeet = cursor.value[Object.keys(row)] === row[Object.keys(row)];
}
}
if (isMeet) {
total++;
if (total >= pageStart && total <= pageEnd) {
data.push(cursor.value);
}
}
}
next();
},
{
indbSocurse,
index,
currentPage,
conditions,
pageSize,
pageStart,
pageEnd
}
);
if (!conditions.length) {
//没有查询条件
total = await indbSocurse.count();
}
//总共多少页
const pageNumber = Math.ceil(total / pageSize);
return {
total,
pageSize,
pageNumber,
data,
currentPage
};
};
同需求。 看看。
@xianzou 是否可以提个pr
感觉您的教程让使用indexdb更加方便,但是目前我还是有一些不清楚的地方,比如如何做分页,尤其是当我们多条件查询的时候做分页,能否添加一下示例,感谢~