Skip to content

Commit 7b264f9

Browse files
committed
fix(routing): flickering (part 1)
1 parent 9650bec commit 7b264f9

File tree

7 files changed

+78
-45
lines changed

7 files changed

+78
-45
lines changed

packages/core/src/components/nav/nav.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ export class NavControllerBase implements NavOutlet {
223223
return null;
224224
}
225225

226+
@Method()
227+
markVisible() {
228+
return Promise.resolve();
229+
}
230+
226231
@Method()
227232
getContentElement(): HTMLElement {
228233
const active = this.getActive();

packages/core/src/components/nav/readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ Return a view controller
7171
#### insertPages()
7272

7373

74+
#### markVisible()
75+
76+
7477
#### pop()
7578

7679

packages/core/src/components/router/utils/dom.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ export function writeNavState(root: HTMLElement, chain: RouteChain, index: numbe
1818
}
1919
const nextEl = node.getContentElement();
2020
if (nextEl) {
21-
return writeNavState(nextEl, chain, index + 1, direction);
21+
return writeNavState(nextEl, chain, index + 1, direction)
22+
.then(() => node.markVisible());
23+
} else {
24+
return node.markVisible();
2225
}
23-
return null;
2426
});
2527
}
2628

packages/core/src/components/router/utils/interfaces.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11

22
export interface NavOutlet {
33
setRouteId(id: any, data: any, direction: number): Promise<boolean>;
4+
markVisible(): Promise<void>;
45
getRouteId(): string;
6+
57
getContentElement(): HTMLElement | null;
68
}
79

packages/core/src/components/tab/tab.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { asyncRaf } from '../../utils/helpers';
99
export class Tab {
1010

1111
private loaded = false;
12-
@Element() el: HTMLElement;
12+
@Element() el: HTMLIonTabElement;
1313

1414
@State() init = false;
1515

@@ -92,7 +92,7 @@ export class Tab {
9292
}
9393

9494
@Method()
95-
setActive(): Promise<any> {
95+
setActive(): Promise<HTMLIonTabElement> {
9696
return this.prepareLazyLoaded().then(() => this.showTab());
9797
}
9898

@@ -104,9 +104,9 @@ export class Tab {
104104
return Promise.resolve();
105105
}
106106

107-
private showTab(): Promise<any|void> {
107+
private showTab(): Promise<HTMLIonTabElement> {
108108
this.active = true;
109-
return Promise.resolve();
109+
return Promise.resolve(this.el);
110110
}
111111

112112
hostData() {

packages/core/src/components/tabs/readme.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,9 @@ Emitted when the tab changes.
240240
#### getTabs()
241241

242242

243+
#### markVisible()
244+
245+
243246
#### select()
244247

245248

packages/core/src/components/tabs/tabs.tsx

Lines changed: 57 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { Config, NavOutlet } from '../../index';
99
export class Tabs implements NavOutlet {
1010
private ids = -1;
1111
private transitioning = false;
12+
private routingView: HTMLIonTabElement;
13+
1214
private tabsId: number = (++tabIds);
1315

1416
@Element() el: HTMLElement;
@@ -73,10 +75,7 @@ export class Tabs implements NavOutlet {
7375
}
7476

7577
componentDidLoad() {
76-
return this.initTabs().then(() => {
77-
const useRouter = !!document.querySelector('ion-router');
78-
return useRouter ? this.initSelect() : Promise.resolve();
79-
});
78+
return this.initTabs().then(() => this.initSelect());
8079
}
8180

8281
componentDidUnload() {
@@ -95,37 +94,8 @@ export class Tabs implements NavOutlet {
9594
*/
9695
@Method()
9796
select(tabOrIndex: number | HTMLIonTabElement): Promise<boolean> {
98-
if (this.transitioning) {
99-
return Promise.resolve(false);
100-
}
101-
const selectedTab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex);
102-
if (!selectedTab) {
103-
return Promise.resolve(false);
104-
}
105-
106-
// Reset rest of tabs
107-
for (const tab of this.tabs) {
108-
if (selectedTab !== tab) {
109-
tab.selected = false;
110-
}
111-
}
112-
113-
const leavingTab = this.selectedTab;
114-
this.transitioning = true;
115-
return selectedTab.setActive().then(() => {
116-
this.transitioning = false;
117-
selectedTab.selected = true;
118-
if (leavingTab !== selectedTab) {
119-
if (leavingTab) {
120-
leavingTab.active = false;
121-
}
122-
this.selectedTab = selectedTab;
123-
this.ionChange.emit(selectedTab);
124-
this.ionNavChanged.emit({isPop: false});
125-
return true;
126-
}
127-
return false;
128-
});
97+
return this.setActive(tabOrIndex)
98+
.then(selectedTab => this.tabSwitch(selectedTab));
12999
}
130100

131101
/**
@@ -161,9 +131,18 @@ export class Tabs implements NavOutlet {
161131
return Promise.resolve(false);
162132
}
163133
const tab = this.tabs.find(t => id === t.getRouteId());
164-
return this.select(tab).then(() => true);
134+
return this.setActive(tab).then(() => {
135+
this.routingView = tab;
136+
return true;
137+
});
165138
}
166139

140+
@Method()
141+
markVisible(): Promise<void> {
142+
this.tabSwitch(this.routingView);
143+
this.routingView = null;
144+
return Promise.resolve();
145+
}
167146

168147
@Method()
169148
getRouteId(): string|null {
@@ -176,7 +155,7 @@ export class Tabs implements NavOutlet {
176155

177156
@Method()
178157
getContentElement(): HTMLElement {
179-
return this.selectedTab;
158+
return this.routingView || this.selectedTab;
180159
}
181160

182161
private initTabs() {
@@ -191,7 +170,7 @@ export class Tabs implements NavOutlet {
191170
return Promise.all(tabPromises);
192171
}
193172

194-
private initSelect() {
173+
private initSelect(): Promise<void> {
195174
if (document.querySelector('ion-router')) {
196175
return Promise.resolve();
197176
}
@@ -205,7 +184,7 @@ export class Tabs implements NavOutlet {
205184
tab.selected = false;
206185
}
207186
}
208-
const promise = selectedTab ? selectedTab.setActive() : Promise.resolve();
187+
const promise = selectedTab ? selectedTab.setActive() : Promise.resolve(null);
209188
return promise.then(() => {
210189
this.selectedTab = selectedTab;
211190
if (selectedTab) {
@@ -222,6 +201,45 @@ export class Tabs implements NavOutlet {
222201
}
223202
}
224203

204+
private setActive(tabOrIndex: number | HTMLIonTabElement): Promise<HTMLIonTabElement|null> {
205+
if (this.transitioning) {
206+
return Promise.resolve(null);
207+
}
208+
const selectedTab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex);
209+
if (!selectedTab) {
210+
return Promise.resolve(null);
211+
}
212+
213+
// Reset rest of tabs
214+
for (const tab of this.tabs) {
215+
if (selectedTab !== tab) {
216+
tab.selected = false;
217+
}
218+
}
219+
220+
this.transitioning = true;
221+
return selectedTab.setActive();
222+
}
223+
224+
private tabSwitch(selectedTab: HTMLIonTabElement | null): boolean {
225+
this.transitioning = false;
226+
if (!selectedTab) {
227+
return false;
228+
}
229+
const leavingTab = this.selectedTab;
230+
selectedTab.selected = true;
231+
if (leavingTab !== selectedTab) {
232+
if (leavingTab) {
233+
leavingTab.active = false;
234+
}
235+
this.selectedTab = selectedTab;
236+
this.ionChange.emit(selectedTab);
237+
this.ionNavChanged.emit({isPop: false});
238+
return true;
239+
}
240+
return false;
241+
}
242+
225243
render() {
226244
const dom = [
227245
<div class='tabs-inner'>

0 commit comments

Comments
 (0)