mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-21 21:15:24 +08:00
perf(nav): minor performance improvements
This commit is contained in:
@ -216,6 +216,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
|
|
||||||
reject && reject(false, false, rejectReason);
|
reject && reject(false, false, rejectReason);
|
||||||
|
|
||||||
|
// let's see if there's another to kick off
|
||||||
this.setTransitioning(false);
|
this.setTransitioning(false);
|
||||||
this._sbCheck();
|
this._sbCheck();
|
||||||
this._nextTrns();
|
this._nextTrns();
|
||||||
@ -226,12 +227,12 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
ti.insertViews = ti.insertViews.filter(v => v !== null);
|
ti.insertViews = ti.insertViews.filter(v => v !== null);
|
||||||
if (ti.insertViews.length === 0) {
|
if (ti.insertViews.length === 0) {
|
||||||
ti.reject('invalid views to insert');
|
ti.reject('invalid views to insert');
|
||||||
return;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (isPresent(ti.removeStart) && !this._views.length && !this._isPortal) {
|
} else if (isPresent(ti.removeStart) && this._views.length === 0 && !this._isPortal) {
|
||||||
ti.reject('no views in the stack to be removed');
|
ti.reject('no views in the stack to be removed');
|
||||||
return;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._queue.push(ti);
|
this._queue.push(ti);
|
||||||
@ -275,15 +276,14 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Only test canLeave/canEnter if there is transition
|
// Only test canLeave/canEnter if there is transition
|
||||||
let requiresTransition = (ti.enteringRequiresTransition || ti.leavingRequiresTransition) && enteringView !== leavingView;
|
const requiresTransition = (ti.enteringRequiresTransition || ti.leavingRequiresTransition) && enteringView !== leavingView;
|
||||||
if (requiresTransition) {
|
if (requiresTransition) {
|
||||||
// views have been initialized, now let's test
|
// views have been initialized, now let's test
|
||||||
// to see if the transition is even allowed or not
|
// to see if the transition is even allowed or not
|
||||||
return this._viewTest(enteringView, leavingView, ti);
|
return this._viewTest(enteringView, leavingView, ti);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this._postViewInit(enteringView, leavingView, ti, ti.resolve);
|
return this._postViewInit(enteringView, leavingView, ti);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,10 +335,12 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
|
|
||||||
const removeStart = ti.removeStart;
|
const removeStart = ti.removeStart;
|
||||||
if (isPresent(removeStart)) {
|
if (isPresent(removeStart)) {
|
||||||
let views = this._views;
|
const views = this._views;
|
||||||
const removeEnd = removeStart + ti.removeCount;
|
const removeEnd = removeStart + ti.removeCount;
|
||||||
for (var i = views.length - 1; i >= 0; i--) {
|
let i: number;
|
||||||
var view = views[i];
|
let view: ViewController;
|
||||||
|
for (i = views.length - 1; i >= 0; i--) {
|
||||||
|
view = views[i];
|
||||||
if ((i < removeStart || i >= removeEnd) && view !== leavingView) {
|
if ((i < removeStart || i >= removeEnd) && view !== leavingView) {
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
@ -347,11 +349,15 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_postViewInit(enteringView: ViewController, leavingView: ViewController, ti: TransitionInstruction, resolve: TransitionResolveFn) {
|
_postViewInit(enteringView: ViewController, leavingView: ViewController, ti: TransitionInstruction) {
|
||||||
assert(leavingView || enteringView, 'Both leavingView and enteringView are null');
|
assert(leavingView || enteringView, 'Both leavingView and enteringView are null');
|
||||||
|
assert(ti.resolve, 'resolve must be valid');
|
||||||
|
assert(ti.reject, 'reject must be valid');
|
||||||
|
|
||||||
const opts = ti.opts || {};
|
const opts = ti.opts || {};
|
||||||
const insertViews = ti.insertViews;
|
const insertViews = ti.insertViews;
|
||||||
const removeStart = ti.removeStart;
|
const removeStart = ti.removeStart;
|
||||||
|
const removeCount = ti.removeCount;
|
||||||
let view: ViewController;
|
let view: ViewController;
|
||||||
let i: number;
|
let i: number;
|
||||||
let destroyQueue: ViewController[];
|
let destroyQueue: ViewController[];
|
||||||
@ -359,10 +365,10 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
// there are views to remove
|
// there are views to remove
|
||||||
if (isPresent(removeStart)) {
|
if (isPresent(removeStart)) {
|
||||||
assert(removeStart >= 0, 'removeStart can not be negative');
|
assert(removeStart >= 0, 'removeStart can not be negative');
|
||||||
assert(ti.removeCount >= 0, 'removeCount can not be negative');
|
assert(removeCount >= 0, 'removeCount can not be negative');
|
||||||
|
|
||||||
destroyQueue = [];
|
destroyQueue = [];
|
||||||
for (i = 0; i < ti.removeCount; i++) {
|
for (i = 0; i < removeCount; i++) {
|
||||||
view = this._views[i + removeStart];
|
view = this._views[i + removeStart];
|
||||||
if (view && view !== enteringView && view !== leavingView) {
|
if (view && view !== enteringView && view !== leavingView) {
|
||||||
destroyQueue.push(view);
|
destroyQueue.push(view);
|
||||||
@ -378,7 +384,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
console.warn(`You can't remove all the pages in the navigation stack. nav.pop() is probably called too many times.`,
|
console.warn(`You can't remove all the pages in the navigation stack. nav.pop() is probably called too many times.`,
|
||||||
this, this.getNativeElement());
|
this, this.getNativeElement());
|
||||||
|
|
||||||
ti.reject && ti.reject('navigation stack needs at least one root page');
|
ti.reject('navigation stack needs at least one root page');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,6 +398,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
// add the views to the
|
// add the views to the
|
||||||
for (i = 0; i < insertViews.length; i++) {
|
for (i = 0; i < insertViews.length; i++) {
|
||||||
view = insertViews[i];
|
view = insertViews[i];
|
||||||
|
assert(view, 'view must be non null');
|
||||||
this._insertViewAt(view, ti.insertStart + i);
|
this._insertViewAt(view, ti.insertStart + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,14 +440,15 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// huzzah! let us transition these views
|
// huzzah! let us transition these views
|
||||||
this._transition(enteringView, leavingView, opts, resolve);
|
this._transition(enteringView, leavingView, opts, ti.resolve);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// they're inserting/removing the views somewhere in the middle or
|
// they're inserting/removing the views somewhere in the middle or
|
||||||
// beginning, so visually nothing needs to animate/transition
|
// beginning, so visually nothing needs to animate/transition
|
||||||
// resolve immediately because there's no animation that's happening
|
// resolve immediately because there's no animation that's happening
|
||||||
resolve(true, false);
|
ti.resolve(true, false);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -488,17 +496,15 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
this._zone.run(this._didLoad.bind(this, view));
|
this._zone.run(this._didLoad.bind(this, view));
|
||||||
}
|
}
|
||||||
|
|
||||||
_viewTest(enteringView: ViewController, leavingView: ViewController, ti: TransitionInstruction) {
|
_viewTest(enteringView: ViewController, leavingView: ViewController, ti: TransitionInstruction): boolean {
|
||||||
const promises: Promise<any>[] = [];
|
const promises: Promise<any>[] = [];
|
||||||
const reject = ti.reject;
|
|
||||||
const resolve = ti.resolve;
|
|
||||||
|
|
||||||
if (leavingView) {
|
if (leavingView) {
|
||||||
const leavingTestResult = leavingView._lifecycleTest('Leave');
|
const leavingTestResult = leavingView._lifecycleTest('Leave');
|
||||||
|
|
||||||
if (leavingTestResult === false) {
|
if (leavingTestResult === false) {
|
||||||
// synchronous reject
|
// synchronous reject
|
||||||
reject((leavingTestResult !== false ? leavingTestResult : `ionViewCanLeave rejected`));
|
ti.reject((leavingTestResult !== false ? leavingTestResult : `ionViewCanLeave rejected`));
|
||||||
return false;
|
return false;
|
||||||
} else if (leavingTestResult instanceof Promise) {
|
} else if (leavingTestResult instanceof Promise) {
|
||||||
// async promise
|
// async promise
|
||||||
@ -511,7 +517,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
|
|
||||||
if (enteringTestResult === false) {
|
if (enteringTestResult === false) {
|
||||||
// synchronous reject
|
// synchronous reject
|
||||||
reject((enteringTestResult !== false ? enteringTestResult : `ionViewCanEnter rejected`));
|
ti.reject((enteringTestResult !== false ? enteringTestResult : `ionViewCanEnter rejected`));
|
||||||
return false;
|
return false;
|
||||||
} else if (enteringTestResult instanceof Promise) {
|
} else if (enteringTestResult instanceof Promise) {
|
||||||
// async promise
|
// async promise
|
||||||
@ -521,19 +527,18 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
|
|
||||||
if (promises.length) {
|
if (promises.length) {
|
||||||
// darn, async promises, gotta wait for them to resolve
|
// darn, async promises, gotta wait for them to resolve
|
||||||
Promise.all(promises)
|
Promise.all(promises).then((values: any[]) => {
|
||||||
.then((values: any[]) => {
|
|
||||||
if (values.some(result => result === false)) {
|
if (values.some(result => result === false)) {
|
||||||
reject(`ionViewCanEnter rejected`);
|
ti.reject(`ionViewCanEnter rejected`);
|
||||||
} else {
|
} else {
|
||||||
this._postViewInit(enteringView, leavingView, ti, resolve);
|
this._postViewInit(enteringView, leavingView, ti);
|
||||||
}
|
}
|
||||||
}).catch(reject);
|
}).catch(ti.reject);
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// synchronous and all tests passed! let's move on already
|
// synchronous and all tests passed! let's move on already
|
||||||
this._postViewInit(enteringView, leavingView, ti, resolve);
|
return this._postViewInit(enteringView, leavingView, ti);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_transition(enteringView: ViewController, leavingView: ViewController, opts: NavOptions, resolve: TransitionResolveFn) {
|
_transition(enteringView: ViewController, leavingView: ViewController, opts: NavOptions, resolve: TransitionResolveFn) {
|
||||||
@ -678,28 +683,31 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_trnsFinish(transition: Transition, opts: NavOptions, resolve: TransitionResolveFn) {
|
_trnsFinish(transition: Transition, opts: NavOptions, resolve: TransitionResolveFn) {
|
||||||
|
const hasCompleted = transition.hasCompleted;
|
||||||
|
const enteringView = transition.enteringView;
|
||||||
|
const leavingView = transition.leavingView;
|
||||||
|
|
||||||
// mainly for testing
|
// mainly for testing
|
||||||
let enteringName: string;
|
let enteringName: string;
|
||||||
let leavingName: string;
|
let leavingName: string;
|
||||||
let hasCompleted = transition.hasCompleted;
|
|
||||||
|
|
||||||
if (hasCompleted) {
|
if (hasCompleted) {
|
||||||
// transition has completed (went from 0 to 1)
|
// transition has completed (went from 0 to 1)
|
||||||
if (transition.enteringView) {
|
if (enteringView) {
|
||||||
enteringName = transition.enteringView.name;
|
enteringName = enteringView.name;
|
||||||
this._didEnter(transition.enteringView);
|
this._didEnter(enteringView);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transition.leavingView) {
|
if (leavingView) {
|
||||||
leavingName = transition.leavingView.name;
|
leavingName = leavingView.name;
|
||||||
this._didLeave(transition.leavingView);
|
this._didLeave(leavingView);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._cleanup(transition.enteringView);
|
this._cleanup(enteringView);
|
||||||
} else {
|
} else {
|
||||||
// If transition does not complete, we have to cleanup anyway, because
|
// If transition does not complete, we have to cleanup anyway, because
|
||||||
// previous pages in the stack are not hidden probably.
|
// previous pages in the stack are not hidden probably.
|
||||||
this._cleanup(transition.leavingView);
|
this._cleanup(leavingView);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (transition.isRoot()) {
|
if (transition.isRoot()) {
|
||||||
@ -754,7 +762,7 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
const views = this._views;
|
const views = this._views;
|
||||||
const index = views.indexOf(view);
|
const index = views.indexOf(view);
|
||||||
assert(index > -1, 'view must be part of the stack');
|
assert(index > -1, 'view must be part of the stack');
|
||||||
if (index > -1) {
|
if (index >= 0) {
|
||||||
views.splice(index, 1);
|
views.splice(index, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -771,10 +779,13 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
// ok, cleanup time!! Destroy all of the views that are
|
// ok, cleanup time!! Destroy all of the views that are
|
||||||
// INACTIVE and come after the active view
|
// INACTIVE and come after the active view
|
||||||
const activeViewIndex = this.indexOf(activeView);
|
const activeViewIndex = this.indexOf(activeView);
|
||||||
|
const views = this._views;
|
||||||
let reorderZIndexes = false;
|
let reorderZIndexes = false;
|
||||||
for (var i = this._views.length - 1; i >= 0; i--) {
|
let view: ViewController;
|
||||||
var view = this._views[i];
|
let i: number;
|
||||||
|
|
||||||
|
for (i = views.length - 1; i >= 0; i--) {
|
||||||
|
view = views[i];
|
||||||
if (i > activeViewIndex) {
|
if (i > activeViewIndex) {
|
||||||
// this view comes after the active view
|
// this view comes after the active view
|
||||||
// let's unload it
|
// let's unload it
|
||||||
@ -791,12 +802,11 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._isPortal) {
|
if (!this._isPortal && reorderZIndexes) {
|
||||||
if (reorderZIndexes) {
|
for (i = 0; i < views.length; i++) {
|
||||||
this._views.forEach(view => {
|
view = views[i];
|
||||||
// ******** DOM WRITE ****************
|
// ******** DOM WRITE ****************
|
||||||
view._setZIndex(view._zIndex + INIT_ZINDEX + 1, this._renderer);
|
view._setZIndex(view._zIndex + INIT_ZINDEX + 1, this._renderer);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -867,7 +877,6 @@ export class NavControllerBase extends Ion implements NavController {
|
|||||||
this._app.viewWillUnload.emit(view);
|
this._app.viewWillUnload.emit(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getActiveChildNav(): any {
|
getActiveChildNav(): any {
|
||||||
return this._children[this._children.length - 1];
|
return this._children[this._children.length - 1];
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user