perf(nav): avoid running zone when it is not needed

This commit is contained in:
Manu Mtz.-Almeida
2016-11-07 20:59:48 +01:00
parent bc5cd7f03f
commit be72d39bd9
3 changed files with 35 additions and 17 deletions

View File

@ -117,7 +117,7 @@ export class NavControllerBase extends Ion implements NavController {
}, done); }, done);
} }
popAll() { popAll(): Promise<any[]> {
let promises: any[] = []; let promises: any[] = [];
for (var i = this._views.length - 1; i >= 0; i--) { for (var i = this._views.length - 1; i >= 0; i--) {
promises.push(this.pop(null)); promises.push(this.pop(null));
@ -133,6 +133,10 @@ export class NavControllerBase extends Ion implements NavController {
}, done); }, done);
} }
removeView(viewController: ViewController, opts?: NavOptions, done?: Function): Promise<any> {
return this.remove(this.indexOf(viewController), 1, opts, done);
}
setRoot(pageOrViewCtrl: any, params?: any, opts?: NavOptions, done?: Function): Promise<any> { setRoot(pageOrViewCtrl: any, params?: any, opts?: NavOptions, done?: Function): Promise<any> {
let viewControllers = [convertToView(this._linker, pageOrViewCtrl, params)]; let viewControllers = [convertToView(this._linker, pageOrViewCtrl, params)];
return this._setPages(viewControllers, opts, done); return this._setPages(viewControllers, opts, done);
@ -330,15 +334,16 @@ export class NavControllerBase extends Ion implements NavController {
const opts = ti.opts || {}; const opts = ti.opts || {};
const insertViews = ti.insertViews; const insertViews = ti.insertViews;
const removeStart = ti.removeStart; const removeStart = ti.removeStart;
let view; let view: ViewController;
let destroyQueue: ViewController[] = []; let i: number;
let destroyQueue: ViewController[];
// 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(ti.removeCount >= 0, 'removeCount can not be negative');
destroyQueue = [];
for (var i = 0; i < ti.removeCount; i++) { for (i = 0; i < ti.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);
@ -356,7 +361,7 @@ export class NavControllerBase extends Ion implements NavController {
} }
// add the views to the // add the views to the
for (var i = 0; i < insertViews.length; i++) { for (i = 0; i < insertViews.length; i++) {
view = insertViews[i]; view = insertViews[i];
this._insertViewAt(view, ti.insertStart + i); this._insertViewAt(view, ti.insertStart + i);
} }
@ -366,22 +371,26 @@ export class NavControllerBase extends Ion implements NavController {
opts.direction = opts.direction || DIRECTION_FORWARD; opts.direction = opts.direction || DIRECTION_FORWARD;
} }
} }
// if the views to be removed are in the beginning or middle // if the views to be removed are in the beginning or middle
// and there is not a view that needs to visually transition out // and there is not a view that needs to visually transition out
// then just destroy them and don't transition anything // then just destroy them and don't transition anything
// batch all of lifecycles together // batch all of lifecycles together
// let's make sure, callbacks are zoned // let's make sure, callbacks are zoned
this._zone.run(() => { if (destroyQueue && destroyQueue.length > 0) {
for (view of destroyQueue) { this._zone.run(() => {
this._willLeave(view); for (i = 0; i < destroyQueue.length; i++) {
this._didLeave(view); view = destroyQueue[i];
this._willUnload(view); this._willLeave(view);
} this._didLeave(view);
}); this._willUnload(view);
}
});
// once all lifecycle events has been delivered, we can safely detroy the views // once all lifecycle events has been delivered, we can safely detroy the views
for (view of destroyQueue) { for (i = 0; i < destroyQueue.length; i++) {
this._destroyView(view); this._destroyView(destroyQueue[i]);
}
} }
if (ti.enteringRequiresTransition || ti.leavingRequiresTransition && enteringView !== leavingView) { if (ti.enteringRequiresTransition || ti.leavingRequiresTransition && enteringView !== leavingView) {

View File

@ -452,6 +452,15 @@ export abstract class NavController {
*/ */
abstract remove(startIndex: number, removeCount?: number, opts?: NavOptions, done?: Function): Promise<any>; abstract remove(startIndex: number, removeCount?: number, opts?: NavOptions, done?: Function): Promise<any>;
/**
* Removes the specified view controller from the nav stack.
*
* @param {ViewController} [viewController] The viewcontroller to remove.
* @param {object} [opts={}] Any options you want to use pass to transtion.
* @returns {Promise} Returns a promise which is resolved when the transition has completed.
*/
abstract removeView(viewController: ViewController, opts?: NavOptions, done?: Function): Promise<any>;
/** /**
* Set the root for the current navigation stack. * Set the root for the current navigation stack.
* @param {Page|ViewController} page The name of the component you want to push on the navigation stack. * @param {Page|ViewController} page The name of the component you want to push on the navigation stack.

View File

@ -179,7 +179,7 @@ export class ViewController {
let options = assign({}, this._leavingOpts, navOptions); let options = assign({}, this._leavingOpts, navOptions);
this._onWillDismiss && this._onWillDismiss(data, role); this._onWillDismiss && this._onWillDismiss(data, role);
return this._nav.remove(this._nav.indexOf(this), 1, options).then(() => { return this._nav.removeView(this, options).then(() => {
this._onDidDismiss && this._onDidDismiss(data, role); this._onDidDismiss && this._onDidDismiss(data, role);
this._onDidDismiss = null; this._onDidDismiss = null;
return data; return data;