修正了refresh的判定逻辑

This commit is contained in:
Xu Chang 2024-12-19 16:13:28 +08:00
parent 89a30cd291
commit 4ec9515086
17 changed files with 105 additions and 62 deletions

View File

@ -41,6 +41,7 @@ declare class UpdateLogManager<ED extends EntityDict & BaseEntityDict, T extends
}
declare abstract class Node<ED extends EntityDict & BaseEntityDict> extends Feature {
private zombie;
protected stale?: boolean;
/**
* 使
*/
@ -68,6 +69,7 @@ declare abstract class Node<ED extends EntityDict & BaseEntityDict> extends Feat
isLoadingMore(): boolean;
saveExtraData(key: string, data: any): void;
loadExtraData(key: string): any;
isStale(): boolean;
abstract getParent(): Node<ED> | undefined;
}
declare abstract class EntityNode<ED extends EntityDict & BaseEntityDict, T extends keyof ED> extends Node<ED> {
@ -107,7 +109,7 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
}> | undefined;
onCacheSync(records: OpRecord<ED>[]): void;
destroy(): void;
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, projection?: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED> | VirtualNode<ED>, path?: string, filters?: NamedFilterItem<ED, T>[], sorters?: NamedSorterItem<ED, T>[], getTotal?: number, pagination?: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>);
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, projection?: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED> | VirtualNode<ED>, path?: string, filters?: NamedFilterItem<ED, T>[], sorters?: NamedSorterItem<ED, T>[], getTotal?: number, pagination?: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>, stale?: boolean);
getPagination(): Pagination;
setPagination(pagination: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>, dontRefresh?: true): void;
addChild(path: string, node: SingleNode<ED, T>): void;
@ -190,7 +192,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
[K: string]: SingleNode<ED, keyof ED> | ListNode<ED, keyof ED>;
};
private filters?;
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, path: string, projection?: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED> | VirtualNode<ED> | ListNode<ED, T>, id?: string, filters?: NamedFilterItem<ED, T>[]);
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, path: string, projection?: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED> | VirtualNode<ED> | ListNode<ED, T>, id?: string, filters?: NamedFilterItem<ED, T>[], stale?: boolean);
getModiOperations(): Array<{
entity: keyof ED;
operation: ED[keyof ED]['Operation'];
@ -243,7 +245,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
}
declare class VirtualNode<ED extends EntityDict & BaseEntityDict> extends Node<ED> {
protected children: Record<string, SingleNode<ED, keyof ED> | ListNode<ED, keyof ED> | VirtualNode<ED>>;
constructor(path?: string, parent?: VirtualNode<ED>);
constructor(path?: string, parent?: VirtualNode<ED>, stale?: boolean);
getModiOperations(): Array<{
entity: keyof ED;
operation: ED[keyof ED]['Operation'];
@ -278,6 +280,7 @@ export type CreateNodeOptions<ED extends EntityDict & BaseEntityDict, T extends
afterExecute?: (operations: ED[T]['Operation'][]) => Promise<void>;
id?: string;
zombie: boolean;
stale?: boolean;
};
export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature {
private logSerailNumber;
@ -310,8 +313,9 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends
isLoading(path: string): boolean | undefined;
isLoadingMore(path: string): boolean | undefined;
isExecuting(path: string): boolean;
private isListDescandent;
private isListDescandentOrStaleBranch;
private isInModiNextBranch;
needNotRefresh(path: string): boolean;
refresh(path: string, pageNumber?: number): Promise<void>;
loadMore(path: string): Promise<void>;
getPagination(path: string): Pagination;

View File

@ -198,6 +198,7 @@ class UpdateLogManager {
}
class Node extends Feature {
zombie = false;
stale;
/**
* 当前有几个组件正在使用这个结点
*/
@ -249,6 +250,9 @@ class Node extends Feature {
loadExtraData(key) {
return this.extraData[key];
}
isStale() {
return !!this.isStale;
}
}
class EntityNode extends Node {
entity;
@ -542,7 +546,7 @@ class ListNode extends EntityNode {
this.children[k].destroy();
}
}
constructor(entity, schema, cache, projection, parent, path, filters, sorters, getTotal, pagination) {
constructor(entity, schema, cache, projection, parent, path, filters, sorters, getTotal, pagination, stale) {
super(entity, schema, cache, projection, parent);
this.filters = filters || [];
this.sorters = sorters || [];
@ -555,6 +559,7 @@ class ListNode extends EntityNode {
total: 0,
count: 0,
} : { ...DEFAULT_PAGINATION };
this.stale = stale;
this.syncHandler = (records) => this.onCacheSync(records);
this.cache.bindOnSync(this.syncHandler);
if (parent) {
@ -1053,11 +1058,12 @@ class SingleNode extends EntityNode {
sr;
children;
filters;
constructor(entity, schema, cache, path, projection, parent, id, filters) {
constructor(entity, schema, cache, path, projection, parent, id, filters, stale) {
super(entity, schema, cache, projection, parent);
this.children = {};
this.sr = {};
this.filters = filters;
this.stale = stale;
// addChild有可能为本结点赋上id值所以要先行
if (parent) {
assert(path);
@ -1637,9 +1643,10 @@ class SingleNode extends EntityNode {
}
class VirtualNode extends Node {
children;
constructor(path, parent) {
constructor(path, parent, stale) {
super();
this.children = {};
this.stale = stale;
if (parent) {
parent.addChild(path, this);
}
@ -1793,7 +1800,7 @@ export class RunningTree extends Feature {
this.logSerailNumber = START_LSN;
}
createNode(options, isPage) {
const { entity, pagination, path: fullPath, filters, sorters, projection, isList, id, getTotal, zombie, } = options;
const { entity, pagination, path: fullPath, filters, sorters, projection, isList, id, getTotal, zombie, stale, } = options;
let node;
const { parent, path } = analyzePath(fullPath);
const parentNode = parent ? this.findNode(parent) : undefined;
@ -1860,16 +1867,16 @@ export class RunningTree extends Feature {
if (isList) {
assert(!(parentNode instanceof ListNode));
// assert(projection, `页面没有定义投影「${path}」`);
node = new ListNode(entity, this.schema, this.cache, projection, parentNode, path, filters, sorters, getTotal, pagination);
node = new ListNode(entity, this.schema, this.cache, projection, parentNode, path, filters, sorters, getTotal, pagination, stale);
}
else {
node = new SingleNode(entity, this.schema, this.cache, path, projection, parentNode, // 过编译
id, filters);
id, filters, stale);
}
}
else {
assert(!parentNode || parentNode instanceof VirtualNode);
node = new VirtualNode(path, parentNode);
node = new VirtualNode(path, parentNode, stale);
}
if (!parentNode) {
assert(!parent && !this.root[path]);
@ -2018,11 +2025,11 @@ export class RunningTree extends Feature {
const node = this.findNode(path);
return node ? node.isExecuting() : false;
}
isListDescandent(path) {
isListDescandentOrStaleBranch(path) {
const node = this.findNode(path);
let parent = node?.getParent();
while (parent) {
if (parent instanceof ListNode) {
if (parent instanceof ListNode || parent.isStale()) {
return true;
}
parent = parent.getParent();
@ -2076,10 +2083,10 @@ export class RunningTree extends Feature {
assert(false);
return false;
}
needNotRefresh(path) {
return this.isListDescandentOrStaleBranch(path) || this.isInModiNextBranch(path);
}
async refresh(path, pageNumber) {
if (this.isInModiNextBranch(path) || this.isListDescandent(path)) {
return;
}
const node = this.findNode(path);
if (!node?.isLoading()) {
if (node instanceof ListNode) {

View File

@ -6,8 +6,8 @@ import { generateNewId } from 'oak-domain/lib/utils/uuid';
import { compareRow, compareRows } from 'oak-domain/lib/utils/row';
export function onPathSet(option, isPage) {
const { props, state } = this;
const { oakPath, oakId, oakFilters, oakZombie } = props;
const { zombie, entity, path, projection, isList, filters, sorters, pagination, getTotal } = option;
const { oakPath, oakId, oakFilters, oakZombie, oakStale } = props;
const { zombie, entity, path, projection, isList, filters, sorters, pagination, getTotal, stale } = option;
const { features } = this;
assert(isPage || zombie === undefined, 'zombie只在页面级别声明');
assert(isPage || path === undefined, 'path只在页面级别自动声明');
@ -109,6 +109,7 @@ export function onPathSet(option, isPage) {
// cascadeActions: cascadeActions && (() => cascadeActions.call(this)),
getTotal: getTotal2,
zombie: isPage ? !!zombie : !!oakZombie,
stale: !!oakStale || !!stale,
}, isPage);
this.addFeatureSub('runningTree', (path2) => {
// 父结点改变,子结点要重渲染

View File

@ -485,7 +485,7 @@ const oakBehavior = Behavior({
this.oakOption.lifetimes?.ready &&
this.oakOption.lifetimes?.ready.call(this);
const { oakFullpath } = this.state;
if (oakFullpath && !this.oakOption.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
this.refresh();
}
else {
@ -788,7 +788,7 @@ export function createComponent(option, features) {
return;
}
const { oakFullpath } = this.state;
if (oakFullpath && !option.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
try {
await this.refresh();
}

View File

@ -646,7 +646,7 @@ export function createComponent(option, features) {
}
try {
const { oakFullpath } = this.state;
if (oakFullpath && !option.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
await this.refresh();
}
else {
@ -704,7 +704,7 @@ export function createComponent(option, features) {
lifetimes?.show && lifetimes.show.call(this);
}
const { oakFullpath } = this.state;
if (oakFullpath && !option.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
this.refresh();
}
else {

1
es/types/Page.d.ts vendored
View File

@ -219,6 +219,7 @@ type OakComponentProperties<ED extends EntityDict & BaseEntityDict, T extends ke
oakParentEntity: string;
oakDisablePulldownRefresh: boolean;
oakZombie: boolean;
oakStale: boolean;
oakAutoUnmount: boolean;
oakActions: string;
oakCascadeActions: string;

View File

@ -41,6 +41,7 @@ declare class UpdateLogManager<ED extends EntityDict & BaseEntityDict, T extends
}
declare abstract class Node<ED extends EntityDict & BaseEntityDict> extends Feature {
private zombie;
protected stale?: boolean;
/**
* 使
*/
@ -68,6 +69,7 @@ declare abstract class Node<ED extends EntityDict & BaseEntityDict> extends Feat
isLoadingMore(): boolean;
saveExtraData(key: string, data: any): void;
loadExtraData(key: string): any;
isStale(): boolean;
abstract getParent(): Node<ED> | undefined;
}
declare abstract class EntityNode<ED extends EntityDict & BaseEntityDict, T extends keyof ED> extends Node<ED> {
@ -107,7 +109,7 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
}> | undefined;
onCacheSync(records: OpRecord<ED>[]): void;
destroy(): void;
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, projection?: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED> | VirtualNode<ED>, path?: string, filters?: NamedFilterItem<ED, T>[], sorters?: NamedSorterItem<ED, T>[], getTotal?: number, pagination?: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>);
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, projection?: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED> | VirtualNode<ED>, path?: string, filters?: NamedFilterItem<ED, T>[], sorters?: NamedSorterItem<ED, T>[], getTotal?: number, pagination?: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>, stale?: boolean);
getPagination(): Pagination;
setPagination(pagination: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>, dontRefresh?: true): void;
addChild(path: string, node: SingleNode<ED, T>): void;
@ -190,7 +192,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
[K: string]: SingleNode<ED, keyof ED> | ListNode<ED, keyof ED>;
};
private filters?;
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, path: string, projection?: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED> | VirtualNode<ED> | ListNode<ED, T>, id?: string, filters?: NamedFilterItem<ED, T>[]);
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED>, path: string, projection?: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED> | VirtualNode<ED> | ListNode<ED, T>, id?: string, filters?: NamedFilterItem<ED, T>[], stale?: boolean);
getModiOperations(): Array<{
entity: keyof ED;
operation: ED[keyof ED]['Operation'];
@ -243,7 +245,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
}
declare class VirtualNode<ED extends EntityDict & BaseEntityDict> extends Node<ED> {
protected children: Record<string, SingleNode<ED, keyof ED> | ListNode<ED, keyof ED> | VirtualNode<ED>>;
constructor(path?: string, parent?: VirtualNode<ED>);
constructor(path?: string, parent?: VirtualNode<ED>, stale?: boolean);
getModiOperations(): Array<{
entity: keyof ED;
operation: ED[keyof ED]['Operation'];
@ -278,6 +280,7 @@ export type CreateNodeOptions<ED extends EntityDict & BaseEntityDict, T extends
afterExecute?: (operations: ED[T]['Operation'][]) => Promise<void>;
id?: string;
zombie: boolean;
stale?: boolean;
};
export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature {
private logSerailNumber;
@ -310,8 +313,9 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends
isLoading(path: string): boolean | undefined;
isLoadingMore(path: string): boolean | undefined;
isExecuting(path: string): boolean;
private isListDescandent;
private isListDescandentOrStaleBranch;
private isInModiNextBranch;
needNotRefresh(path: string): boolean;
refresh(path: string, pageNumber?: number): Promise<void>;
loadMore(path: string): Promise<void>;
getPagination(path: string): Pagination;

View File

@ -201,6 +201,7 @@ class UpdateLogManager {
}
class Node extends Feature_1.Feature {
zombie = false;
stale;
/**
* 当前有几个组件正在使用这个结点
*/
@ -252,6 +253,9 @@ class Node extends Feature_1.Feature {
loadExtraData(key) {
return this.extraData[key];
}
isStale() {
return !!this.isStale;
}
}
class EntityNode extends Node {
entity;
@ -545,7 +549,7 @@ class ListNode extends EntityNode {
this.children[k].destroy();
}
}
constructor(entity, schema, cache, projection, parent, path, filters, sorters, getTotal, pagination) {
constructor(entity, schema, cache, projection, parent, path, filters, sorters, getTotal, pagination, stale) {
super(entity, schema, cache, projection, parent);
this.filters = filters || [];
this.sorters = sorters || [];
@ -558,6 +562,7 @@ class ListNode extends EntityNode {
total: 0,
count: 0,
} : { ...DEFAULT_PAGINATION };
this.stale = stale;
this.syncHandler = (records) => this.onCacheSync(records);
this.cache.bindOnSync(this.syncHandler);
if (parent) {
@ -1056,11 +1061,12 @@ class SingleNode extends EntityNode {
sr;
children;
filters;
constructor(entity, schema, cache, path, projection, parent, id, filters) {
constructor(entity, schema, cache, path, projection, parent, id, filters, stale) {
super(entity, schema, cache, projection, parent);
this.children = {};
this.sr = {};
this.filters = filters;
this.stale = stale;
// addChild有可能为本结点赋上id值所以要先行
if (parent) {
(0, assert_1.assert)(path);
@ -1640,9 +1646,10 @@ class SingleNode extends EntityNode {
}
class VirtualNode extends Node {
children;
constructor(path, parent) {
constructor(path, parent, stale) {
super();
this.children = {};
this.stale = stale;
if (parent) {
parent.addChild(path, this);
}
@ -1796,7 +1803,7 @@ class RunningTree extends Feature_1.Feature {
this.logSerailNumber = START_LSN;
}
createNode(options, isPage) {
const { entity, pagination, path: fullPath, filters, sorters, projection, isList, id, getTotal, zombie, } = options;
const { entity, pagination, path: fullPath, filters, sorters, projection, isList, id, getTotal, zombie, stale, } = options;
let node;
const { parent, path } = analyzePath(fullPath);
const parentNode = parent ? this.findNode(parent) : undefined;
@ -1863,16 +1870,16 @@ class RunningTree extends Feature_1.Feature {
if (isList) {
(0, assert_1.assert)(!(parentNode instanceof ListNode));
// assert(projection, `页面没有定义投影「${path}」`);
node = new ListNode(entity, this.schema, this.cache, projection, parentNode, path, filters, sorters, getTotal, pagination);
node = new ListNode(entity, this.schema, this.cache, projection, parentNode, path, filters, sorters, getTotal, pagination, stale);
}
else {
node = new SingleNode(entity, this.schema, this.cache, path, projection, parentNode, // 过编译
id, filters);
id, filters, stale);
}
}
else {
(0, assert_1.assert)(!parentNode || parentNode instanceof VirtualNode);
node = new VirtualNode(path, parentNode);
node = new VirtualNode(path, parentNode, stale);
}
if (!parentNode) {
(0, assert_1.assert)(!parent && !this.root[path]);
@ -2021,11 +2028,11 @@ class RunningTree extends Feature_1.Feature {
const node = this.findNode(path);
return node ? node.isExecuting() : false;
}
isListDescandent(path) {
isListDescandentOrStaleBranch(path) {
const node = this.findNode(path);
let parent = node?.getParent();
while (parent) {
if (parent instanceof ListNode) {
if (parent instanceof ListNode || parent.isStale()) {
return true;
}
parent = parent.getParent();
@ -2079,10 +2086,10 @@ class RunningTree extends Feature_1.Feature {
(0, assert_1.assert)(false);
return false;
}
needNotRefresh(path) {
return this.isListDescandentOrStaleBranch(path) || this.isInModiNextBranch(path);
}
async refresh(path, pageNumber) {
if (this.isInModiNextBranch(path) || this.isListDescandent(path)) {
return;
}
const node = this.findNode(path);
if (!node?.isLoading()) {
if (node instanceof ListNode) {

View File

@ -9,8 +9,8 @@ const uuid_1 = require("oak-domain/lib/utils/uuid");
const row_1 = require("oak-domain/lib/utils/row");
function onPathSet(option, isPage) {
const { props, state } = this;
const { oakPath, oakId, oakFilters, oakZombie } = props;
const { zombie, entity, path, projection, isList, filters, sorters, pagination, getTotal } = option;
const { oakPath, oakId, oakFilters, oakZombie, oakStale } = props;
const { zombie, entity, path, projection, isList, filters, sorters, pagination, getTotal, stale } = option;
const { features } = this;
(0, assert_1.assert)(isPage || zombie === undefined, 'zombie只在页面级别声明');
(0, assert_1.assert)(isPage || path === undefined, 'path只在页面级别自动声明');
@ -112,6 +112,7 @@ function onPathSet(option, isPage) {
// cascadeActions: cascadeActions && (() => cascadeActions.call(this)),
getTotal: getTotal2,
zombie: isPage ? !!zombie : !!oakZombie,
stale: !!oakStale || !!stale,
}, isPage);
this.addFeatureSub('runningTree', (path2) => {
// 父结点改变,子结点要重渲染

View File

@ -488,7 +488,7 @@ const oakBehavior = Behavior({
this.oakOption.lifetimes?.ready &&
this.oakOption.lifetimes?.ready.call(this);
const { oakFullpath } = this.state;
if (oakFullpath && !this.oakOption.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
this.refresh();
}
else {
@ -791,7 +791,7 @@ function createComponent(option, features) {
return;
}
const { oakFullpath } = this.state;
if (oakFullpath && !option.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
try {
await this.refresh();
}

View File

@ -651,7 +651,7 @@ function createComponent(option, features) {
}
try {
const { oakFullpath } = this.state;
if (oakFullpath && !option.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
await this.refresh();
}
else {
@ -709,7 +709,7 @@ function createComponent(option, features) {
lifetimes?.show && lifetimes.show.call(this);
}
const { oakFullpath } = this.state;
if (oakFullpath && !option.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
this.refresh();
}
else {

1
lib/types/Page.d.ts vendored
View File

@ -219,6 +219,7 @@ type OakComponentProperties<ED extends EntityDict & BaseEntityDict, T extends ke
oakParentEntity: string;
oakDisablePulldownRefresh: boolean;
oakZombie: boolean;
oakStale: boolean;
oakAutoUnmount: boolean;
oakActions: string;
oakCascadeActions: string;

View File

@ -250,6 +250,7 @@ class UpdateLogManager<ED extends EntityDict & BaseEntityDict, T extends keyof E
abstract class Node<ED extends EntityDict & BaseEntityDict> extends Feature {
private zombie: boolean = false;
protected stale?: boolean;
/**
* 使
*/
@ -323,6 +324,10 @@ abstract class Node<ED extends EntityDict & BaseEntityDict> extends Feature {
return this.extraData[key];
}
isStale() {
return !!this.isStale;
}
abstract getParent(): Node<ED> | undefined;
}
@ -678,7 +683,8 @@ class ListNode<
filters?: NamedFilterItem<ED, T>[],
sorters?: NamedSorterItem<ED, T>[],
getTotal?: number,
pagination?: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>
pagination?: Pick<Pagination, 'currentPage' | 'pageSize' | 'randomRange'>,
stale?: boolean
) {
super(entity, schema, cache, projection, parent);
this.filters = filters || [];
@ -692,6 +698,7 @@ class ListNode<
total: 0,
count: 0,
} : { ...DEFAULT_PAGINATION };
this.stale = stale;
this.syncHandler = (records) => this.onCacheSync(records);
this.cache.bindOnSync(this.syncHandler);
@ -1315,12 +1322,14 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
projection?: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>),
parent?: SingleNode<ED, keyof ED> | VirtualNode<ED> | ListNode<ED, T>,
id?: string,
filters?: NamedFilterItem<ED, T>[]
filters?: NamedFilterItem<ED, T>[],
stale?: boolean
) {
super(entity, schema, cache, projection, parent);
this.children = {};
this.sr = {};
this.filters = filters;
this.stale = stale;
// addChild有可能为本结点赋上id值所以要先行
if (parent) {
@ -1959,9 +1968,10 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
class VirtualNode<ED extends EntityDict & BaseEntityDict> extends Node<ED> {
protected children: Record<string, SingleNode<ED, keyof ED> | ListNode<ED, keyof ED> | VirtualNode<ED>>;
constructor(path?: string, parent?: VirtualNode<ED>) {
constructor(path?: string, parent?: VirtualNode<ED>, stale?: boolean) {
super();
this.children = {};
this.stale = stale;
if (parent) {
parent.addChild(path!, this);
}
@ -2123,6 +2133,7 @@ export type CreateNodeOptions<ED extends EntityDict & BaseEntityDict, T extends
afterExecute?: (operations: ED[T]['Operation'][]) => Promise<void>;
id?: string;
zombie: boolean;
stale?: boolean;
// createData?: CreateDataDef<ED, T>; // 暂不支持
};
@ -2173,6 +2184,7 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
id,
getTotal,
zombie,
stale,
} = options;
let node: ListNode<ED, T> | SingleNode<ED, T> | VirtualNode<ED> | undefined;
const { parent, path } = analyzePath(fullPath);
@ -2255,7 +2267,8 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
filters,
sorters,
getTotal,
pagination
pagination,
stale,
);
} else {
node = new SingleNode<ED, T>(
@ -2266,12 +2279,13 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
projection,
parentNode as VirtualNode<ED>, // 过编译
id,
filters
filters,
stale
);
}
} else {
assert(!parentNode || parentNode instanceof VirtualNode);
node = new VirtualNode(path, parentNode);
node = new VirtualNode(path, parentNode, stale);
}
if (!parentNode) {
assert(!parent && !this.root[path]);
@ -2466,11 +2480,11 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
return node ? node.isExecuting() : false;
}
private isListDescandent(path: string) {
private isListDescandentOrStaleBranch(path: string) {
const node = this.findNode(path);
let parent = node?.getParent();
while (parent) {
if (parent instanceof ListNode) {
if (parent instanceof ListNode || parent.isStale()) {
return true;
}
parent = parent.getParent();
@ -2480,7 +2494,7 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
// 判断当前结点是否在:next的路径上
// 当前判断规则是:在:next的分岔结点上如果有前项结点或者:next结点本身是一个create则不再刷新
private isInModiNextBranch(path: string) {
private isInModiNextBranch(path: string) {
if (!path.includes(MODI_NEXT_PATH_SUFFIX)) {
return false;
}
@ -2531,10 +2545,11 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
return false;
}
needNotRefresh(path: string) {
return this.isListDescandentOrStaleBranch(path) || this.isInModiNextBranch(path);
}
async refresh(path: string, pageNumber?: number) {
if (this.isInModiNextBranch(path) || this.isListDescandent(path)) {
return;
}
const node = this.findNode(path);
if (!node?.isLoading()) {
if (node instanceof ListNode) {

View File

@ -35,8 +35,8 @@ export function onPathSet<
option: OakComponentOption<any, ED, T, Cxt, FrontCxt, any, any, any, {}, {}, {}>,
isPage: boolean): Partial<OakComponentData<ED, T>> {
const { props, state } = this;
const { oakPath, oakId, oakFilters, oakZombie } = props as ComponentProps<ED, T, {}>;
const { zombie, entity, path, projection, isList, filters, sorters, pagination, getTotal } = option;
const { oakPath, oakId, oakFilters, oakZombie, oakStale } = props as ComponentProps<ED, T, {}>;
const { zombie, entity, path, projection, isList, filters, sorters, pagination, getTotal, stale } = option;
const { features } = this;
assert(isPage || zombie === undefined, 'zombie只在页面级别声明');
@ -151,6 +151,7 @@ export function onPathSet<
// cascadeActions: cascadeActions && (() => cascadeActions.call(this)),
getTotal: getTotal2,
zombie: isPage ? !!zombie : !!oakZombie,
stale: !!oakStale || !!stale,
}, isPage);
this.addFeatureSub('runningTree', (path2: string) => {
// 父结点改变,子结点要重渲染

View File

@ -709,7 +709,7 @@ const oakBehavior = Behavior<
this.oakOption.lifetimes?.ready.call(this);
const { oakFullpath } = this.state;
if (oakFullpath && !this.oakOption.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
this.refresh();
} else {
this.reRender();
@ -1113,7 +1113,7 @@ export function createComponent<
return;
}
const { oakFullpath } = this.state;
if (oakFullpath && !option.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
try {
await this.refresh();
}

View File

@ -979,7 +979,7 @@ export function createComponent<
try {
const { oakFullpath } = this.state;
if (oakFullpath && !option.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
await this.refresh();
}
else {
@ -1047,7 +1047,7 @@ export function createComponent<
lifetimes?.show && lifetimes.show.call(this);
}
const { oakFullpath } = this.state;
if (oakFullpath && !option.stale) {
if (oakFullpath && !this.features.runningTree.needNotRefresh(oakFullpath)) {
this.refresh();
}
else {

View File

@ -405,6 +405,7 @@ type OakComponentProperties<
oakParentEntity: string;
oakDisablePulldownRefresh: boolean;
oakZombie: boolean; // 表示页面unmount时不析构runningTree上的数据
oakStale: boolean; // 表示页面不需要主动刷新数据
oakAutoUnmount: boolean; // 原先需要手动让component卸载已经废弃
oakActions: string;
oakCascadeActions: string;