iter(g254): 派生后页码越界回写内核状态
This commit is contained in:
@@ -81,7 +81,9 @@ export function createTable<T>(
|
||||
return cachedBase;
|
||||
}
|
||||
|
||||
/*** 可见行模型:依序过插件 derive(filter → sort → paginate);paged=false 时跳过分页阶段取全量派生行 ***/
|
||||
/*** 可见行模型:依序过插件 derive(filter → sort → paginate);paged=false 时跳过分页阶段取全量派生行
|
||||
* 派生末尾跑一轮 settle:插件可把派生期算出的生效值回写自己的状态切片(如页码越界钳制),
|
||||
* 保证 state 与视图一致;回写只走 onStateChange、不广播订阅,避免在读取中重入。 ***/
|
||||
function getVisibleRows(paged = true): RowModel<T> {
|
||||
ctx.paged = paged; // 由插件自行判断是否裁剪,核心不认插件细节
|
||||
let model = baseModel();
|
||||
@@ -89,6 +91,13 @@ export function createTable<T>(
|
||||
if (p.derive) model = p.derive(model, state, ctx);
|
||||
}
|
||||
ctx.paged = true; // 还原缺省,避免影响后续调用
|
||||
let settled = false;
|
||||
for (const p of plugins) {
|
||||
if (!p.settle) continue;
|
||||
const next = p.settle(state);
|
||||
if (next !== state) { state = next; settled = true; }
|
||||
}
|
||||
if (settled) onStateChange?.(state); // 状态被收敛:回调通知外部,订阅方靠本次读取结果自更新
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ export function paginationPlugin<T = unknown>(): TablePlugin<T> {
|
||||
let lastPage: { page: number; pageSize: number } | null = null;
|
||||
let cached: RowModel<T> | null = null;
|
||||
let pageInfo: PageInfo = { page: 1, pageSize: 20, totalPages: 1 };
|
||||
let fresh = false; // 快照是否来自「按当前 state 完整派生」,settle 只认新鲜快照
|
||||
|
||||
return {
|
||||
name: 'pagination',
|
||||
@@ -34,7 +35,7 @@ export function paginationPlugin<T = unknown>(): TablePlugin<T> {
|
||||
}
|
||||
},
|
||||
derive(model: RowModel<T>, state: TableState, ctx: DeriveContext<T>): RowModel<T> {
|
||||
if (ctx.paged === false) return model; // 不分页:原样放行上游模型(导出全量行)
|
||||
if (ctx.paged === false) { fresh = false; return model; } // 不分页:原样放行上游模型(导出全量行)
|
||||
if (model === lastInput && state.pagination === lastPage && cached) return cached;
|
||||
const { page, pageSize } = state.pagination;
|
||||
const totalPages = Math.max(1, Math.ceil(model.total / pageSize));
|
||||
@@ -48,8 +49,14 @@ export function paginationPlugin<T = unknown>(): TablePlugin<T> {
|
||||
pageInfo = { page: safePage, pageSize, totalPages };
|
||||
lastInput = model;
|
||||
lastPage = state.pagination;
|
||||
fresh = true;
|
||||
return cached;
|
||||
},
|
||||
settle(state: TableState): TableState {
|
||||
// 只把「当前 state 派生出的生效页」回写;快照过期(未按当前 state 派生)时不动,避免写入错误页码
|
||||
if (!fresh || state.pagination !== lastPage || pageInfo.page === state.pagination.page) return state;
|
||||
return { ...state, pagination: { ...state.pagination, page: pageInfo.page } };
|
||||
},
|
||||
api(table: TableInstance<T>) {
|
||||
return {
|
||||
setPage: (page: number) => table.dispatch({ type: 'setPage', page }),
|
||||
|
||||
@@ -66,11 +66,12 @@ export interface DeriveContext<T = unknown> {
|
||||
getKey(row: T): RowKey; // 行标识取值
|
||||
}
|
||||
|
||||
/*** 插件三钩子:patchState 改状态、derive 插入数据管线、api 向实例注入方法 ***/
|
||||
/*** 插件四钩子:patchState 改状态、derive 插入数据管线、settle 派生后收敛自身状态、api 向实例注入方法 ***/
|
||||
export interface TablePlugin<T = unknown> {
|
||||
name: string; // 插件名,诊断用
|
||||
patchState?(state: TableState, action: Action): TableState; // 处理自己关心的动作,无关动作原样返回
|
||||
derive?(model: RowModel<T>, state: TableState, ctx: DeriveContext<T>): RowModel<T>; // 插入派生管线阶段
|
||||
settle?(state: TableState): TableState; // 派生后回写修正(如页码越界钳制);无需修正须原样返回同一引用
|
||||
api?(table: TableInstance<T>): Record<string, unknown>; // 向实例注入便捷方法
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user