diff --git a/packages/abc/reuse-tab/reuse-tab.component.ts b/packages/abc/reuse-tab/reuse-tab.component.ts index 2cd308fd6..611a2a075 100644 --- a/packages/abc/reuse-tab/reuse-tab.component.ts +++ b/packages/abc/reuse-tab/reuse-tab.component.ts @@ -170,7 +170,7 @@ export class ReuseTabComponent implements OnInit, OnChanges { const url = this.curUrl; let addCurrent = ls.findIndex(w => w.url === url) === -1; - if (ls.length && notify && notify.active === 'close' && notify.url === url) { + if (notify && notify.active === 'close' && notify.url === url) { addCurrent = false; let toPos = 0; const curItem = this.list.find(w => w.url === url)!; @@ -186,15 +186,9 @@ export class ReuseTabComponent implements OnInit, OnChanges { if (addCurrent) { const addPos = this.pos + 1; - const curItem = this.genCurItem(); - ls.splice(addPos, 0, curItem); + ls.splice(addPos, 0, this.genCurItem()); // Attach to cache - const snapshotTrue = this.srv.getTruthRoute(this.route.snapshot); - this.srv.items.splice(addPos, 0, { - title: this.srv.getTitle(url, snapshotTrue), - url, - closable: curItem.closable - }); + this.srv.saveCache(this.route.snapshot, null, addPos); } ls.forEach((item, index) => (item.index = index)); diff --git a/packages/abc/reuse-tab/reuse-tab.service.spec.ts b/packages/abc/reuse-tab/reuse-tab.service.spec.ts index 909f960a3..b725dac83 100644 --- a/packages/abc/reuse-tab/reuse-tab.service.spec.ts +++ b/packages/abc/reuse-tab/reuse-tab.service.spec.ts @@ -17,7 +17,7 @@ class MockMenuService { } } class MockRouter { - navigateByUrl = jasmine.createSpy(); + navigateByUrl = jasmine.createSpy().and.returnValue(Promise.resolve(true)); get events(): NzSafeAny { return { subscribe: () => { @@ -69,7 +69,7 @@ describe('abc: reuse-tab(service)', () => { Array(count) .fill({}) .forEach((_item: NzSafeAny, index: number) => { - srv.store(getSnapshot(index + 1, urlTpl), { a: 1 }); + srv.saveCache(getSnapshot(index + 1, urlTpl), { a: 1 }); }); } @@ -95,21 +95,21 @@ describe('abc: reuse-tab(service)', () => { }); it('should be close oldest page', () => { srv.max = 2; - srv.store(getSnapshot(1), {}); - srv.store(getSnapshot(2), {}); - srv.store(getSnapshot(3), {}); + srv.saveCache(getSnapshot(1), {}); + srv.saveCache(getSnapshot(2), {}); + srv.saveCache(getSnapshot(3), {}); expect(srv.count).toBe(2); - srv.store(getSnapshot(4), {}); + srv.saveCache(getSnapshot(4), {}); expect(srv.count).toBe(2); }); it('should be ingore close when all is not closable', () => { srv.max = 2; - srv.store(getSnapshot(1), {}); - srv.store(getSnapshot(2), {}); + srv.saveCache(getSnapshot(1), {}); + srv.saveCache(getSnapshot(2), {}); srv.items.forEach(i => (i.closable = false)); - srv.store(getSnapshot(3), {}); + srv.saveCache(getSnapshot(3), {}); expect(srv.count).toBe(3); - srv.store(getSnapshot(4), {}); + srv.saveCache(getSnapshot(4), {}); expect(srv.count).toBe(3); }); }); @@ -313,7 +313,7 @@ describe('abc: reuse-tab(service)', () => { destroy: jasmine.createSpy('destroy') } }; - srv.store(getSnapshot(3), instance); + srv.saveCache(getSnapshot(3), instance); srv.close('/a/3'); expect(instance.componentRef.destroy).toHaveBeenCalled(); }); @@ -377,17 +377,19 @@ describe('abc: reuse-tab(service)', () => { srv.refresh(true); }); describe('#replace', () => { - it('should be navigate to new url', () => { + it('should be navigate to new url', fakeAsync(() => { expect(router.navigateByUrl).not.toHaveBeenCalled(); srv.replace('/a/1'); + tick(); expect(router.navigateByUrl).toHaveBeenCalled(); - }); - it('should be closed current router after navigate to new url', () => { + })); + it('should be closed current router after navigate to new url', fakeAsync(() => { genCached(1, ''); expect(router.navigateByUrl).not.toHaveBeenCalled(); srv.replace('/b'); + tick(); expect(router.navigateByUrl).toHaveBeenCalled(); - }); + })); }); describe('#keepingScroll', () => { it('should get keepingScroll from service', () => { @@ -451,7 +453,7 @@ describe('abc: reuse-tab(service)', () => { it(`can't hit when remove current page`, () => { const snapshot = getSnapshot(1); expect(srv.shouldDetach(snapshot)).toBe(true); - srv.store(snapshot, {}); + srv.saveCache(snapshot, {}); srv.close(srv.getUrl(snapshot)); expect(srv.shouldDetach(snapshot)).toBe(false); }); @@ -465,18 +467,18 @@ describe('abc: reuse-tab(service)', () => { }); it(`should be store a new route`, () => { expect(srv.count).toBe(2); - srv.store(getSnapshot(3), {}); + srv.saveCache(getSnapshot(3)); expect(srv.count).toBe(3); }); it(`should be store a exists route`, () => { expect(srv.count).toBe(2); - srv.store(getSnapshot(1), {}); + srv.saveCache(getSnapshot(1)); expect(srv.count).toBe(2); }); it(`should be store a route when out of cache count`, () => { srv.max = 2; expect(srv.count).toBe(2); - srv.store(getSnapshot(3), { componentRef: {} }); + srv.saveCache(getSnapshot(3), { componentRef: {} }); expect(srv.count).toBe(2); }); it(`should be run _onReuseDestroy event hook`, () => { @@ -487,7 +489,9 @@ describe('abc: reuse-tab(service)', () => { } } }; - srv.store(getSnapshot(3), handle); + const snapshot = getSnapshot(3); + srv.saveCache(snapshot, handle); + srv.store(snapshot, handle); expect(handle.componentRef.instance._onReuseDestroy).toHaveBeenCalled(); }); }); @@ -537,7 +541,7 @@ describe('abc: reuse-tab(service)', () => { }; const snapshot = getSnapshot(3); // handle - srv.store(snapshot, handle); + srv.saveCache(snapshot, handle); // mock activate router srv.store(snapshot, null); tick(101); diff --git a/packages/abc/reuse-tab/reuse-tab.service.ts b/packages/abc/reuse-tab/reuse-tab.service.ts index ee369b199..27d3a6a9e 100644 --- a/packages/abc/reuse-tab/reuse-tab.service.ts +++ b/packages/abc/reuse-tab/reuse-tab.service.ts @@ -8,7 +8,7 @@ import { Router, ROUTER_CONFIGURATION } from '@angular/router'; -import { BehaviorSubject, Observable, timer, Unsubscribable } from 'rxjs'; +import { BehaviorSubject, Observable, take, timer, Unsubscribable } from 'rxjs'; import { Menu, MenuService } from '@delon/theme'; import { ScrollService } from '@delon/util/browser'; @@ -441,6 +441,35 @@ export class ReuseTabService implements OnDestroy { return this.can(route); } + saveCache(snapshot: ActivatedRouteSnapshot, _handle?: NzSafeAny, pos?: number): void { + const snapshotTrue = this.getTruthRoute(snapshot); + const url = this.getUrl(snapshot); + const idx = this.index(url); + const item: ReuseTabCached = { + title: this.getTitle(url, snapshotTrue), + url, + closable: this.getClosable(url, snapshot), + _snapshot: snapshot, + _handle + }; + if (idx < 0) { + this.items.splice(pos ?? this.items.length, 0, item); + if (this.count > this._max) { + // Get the oldest closable location + const closeIdx = this.items.findIndex(w => w.url !== url && w.closable!); + if (closeIdx !== -1) { + const closeItem = this.items[closeIdx]; + this.remove(closeIdx, false); + timer(1) + .pipe(take(1)) + .subscribe(() => this._cachedChange.next({ active: 'close', url: closeItem.url, list: this.cached.list })); + } + } + } else { + this.items[idx] = item; + } + } + /** * 存储 */ @@ -449,6 +478,10 @@ export class ReuseTabService implements OnDestroy { const idx = this.index(url); if (idx === -1) return; + if (_handle != null) { + this.saveCache(_snapshot, _handle); + } + const list = this.cached.list; const item: ReuseTabCached = { @@ -463,7 +496,9 @@ export class ReuseTabService implements OnDestroy { // For better reliability, we need to wait for the component to be attached before call _onReuseInit const cahcedComponentRef = list[idx]._handle?.componentRef; if (_handle == null && cahcedComponentRef != null) { - timer(100).subscribe(() => this.runHook('_onReuseInit', cahcedComponentRef)); + timer(100) + .pipe(take(1)) + .subscribe(() => this.runHook('_onReuseInit', cahcedComponentRef)); } list[idx] = item; this.removeUrlBuffer = null; @@ -487,11 +522,6 @@ export class ReuseTabService implements OnDestroy { const ret = !!(data && data._handle); this.di('#shouldAttach', ret, url); if (!ret) { - if (this.count >= this._max) { - // Get the oldest closable location - const closeIdx = this.items.findIndex(w => w.url !== url && w.closable!); - if (closeIdx !== -1) this.remove(closeIdx, false); - } this._cachedChange.next({ active: 'add', url, list: this.cached.list }); } return ret;