mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
perf(angular): skip zone
This commit is contained in:
@ -10,7 +10,14 @@ export function appInitialize(config: Config, doc: Document, zone: NgZone) {
|
||||
if (win) {
|
||||
const Ionic = win.Ionic = win.Ionic || {};
|
||||
|
||||
Ionic.config = config;
|
||||
Ionic.config = {
|
||||
...config,
|
||||
_zoneGate: (h: any) => zone.run(h)
|
||||
};
|
||||
|
||||
const aelFn = '__zone_symbol__addEventListener' in (document.body as any)
|
||||
? '__zone_symbol__addEventListener'
|
||||
: 'addEventListener';
|
||||
|
||||
return applyPolyfills().then(() => {
|
||||
return defineCustomElements(win, {
|
||||
@ -23,41 +30,13 @@ export function appInitialize(config: Config, doc: Document, zone: NgZone) {
|
||||
});
|
||||
},
|
||||
ael(elm, eventName, cb, opts) {
|
||||
if ((elm as any).__zone_symbol__addEventListener && skipZone(eventName)) {
|
||||
(elm as any).__zone_symbol__addEventListener(eventName, cb, opts);
|
||||
} else {
|
||||
elm.addEventListener(eventName, cb, opts);
|
||||
}
|
||||
(elm as any)[aelFn](eventName, cb, opts);
|
||||
},
|
||||
rel(elm, eventName, cb, opts) {
|
||||
if ((elm as any).__zone_symbol__removeEventListener && skipZone(eventName)) {
|
||||
(elm as any).__zone_symbol__removeEventListener(eventName, cb, opts);
|
||||
} else {
|
||||
elm.removeEventListener(eventName, cb, opts);
|
||||
}
|
||||
elm.removeEventListener(eventName, cb, opts);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const SKIP_ZONE = [
|
||||
'scroll',
|
||||
'resize',
|
||||
|
||||
'touchstart',
|
||||
'touchmove',
|
||||
'touchend',
|
||||
|
||||
'mousedown',
|
||||
'mousemove',
|
||||
'mouseup',
|
||||
|
||||
'ionStyle',
|
||||
'ionTabButtonClick'
|
||||
];
|
||||
|
||||
function skipZone(eventName: string) {
|
||||
return SKIP_ZONE.indexOf(eventName) >= 0;
|
||||
}
|
||||
|
@ -42,16 +42,14 @@ export class ValueAccessor implements ControlValueAccessor {
|
||||
}
|
||||
|
||||
export function setIonicClasses(element: ElementRef) {
|
||||
requestAnimationFrame(() => {
|
||||
const input = element.nativeElement as HTMLElement;
|
||||
const classes = getClasses(input);
|
||||
setClasses(input, classes);
|
||||
const input = element.nativeElement as HTMLElement;
|
||||
const classes = getClasses(input);
|
||||
setClasses(input, classes);
|
||||
|
||||
const item = input.closest('ion-item');
|
||||
if (item) {
|
||||
setClasses(item, classes);
|
||||
}
|
||||
});
|
||||
const item = input.closest('ion-item');
|
||||
if (item) {
|
||||
setClasses(item, classes);
|
||||
}
|
||||
}
|
||||
|
||||
function getClasses(element: HTMLElement) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { Attribute, ChangeDetectorRef, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, NgZone, OnDestroy, OnInit, Optional, Output, SkipSelf, ViewContainerRef } from '@angular/core';
|
||||
import { Attribute, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, NgZone, OnDestroy, OnInit, Optional, Output, SkipSelf, ViewContainerRef } from '@angular/core';
|
||||
import { ActivatedRoute, ChildrenOutletContexts, OutletContext, PRIMARY_OUTLET, Router } from '@angular/router';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, switchMap } from 'rxjs/operators';
|
||||
@ -57,7 +57,6 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
private resolver: ComponentFactoryResolver,
|
||||
@Attribute('name') name: string,
|
||||
@Optional() @Attribute('tabs') tabs: string,
|
||||
private changeDetector: ChangeDetectorRef,
|
||||
private config: Config,
|
||||
private navCtrl: NavController,
|
||||
commonLocation: Location,
|
||||
@ -206,12 +205,11 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
// Calling `markForCheck` to make sure we will run the change detection when the
|
||||
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
|
||||
enteringView = this.stackCtrl.createView(this.activated, activatedRoute);
|
||||
enteringView.ref.changeDetectorRef.detectChanges();
|
||||
|
||||
// Store references to the proxy by component
|
||||
this.proxyMap.set(cmpRef.instance, activatedRouteProxy);
|
||||
this.currentActivatedRoute$.next({ component: cmpRef.instance, activatedRoute });
|
||||
|
||||
this.changeDetector.markForCheck();
|
||||
}
|
||||
|
||||
this.activatedView = enteringView;
|
||||
|
@ -44,11 +44,7 @@ export class StackController {
|
||||
|
||||
getExistingView(activatedRoute: ActivatedRoute): RouteView | undefined {
|
||||
const activatedUrlKey = getUrl(this.router, activatedRoute);
|
||||
const view = this.views.find(vw => vw.url === activatedUrlKey);
|
||||
if (view) {
|
||||
view.ref.changeDetectorRef.reattach();
|
||||
}
|
||||
return view;
|
||||
return this.views.find(vw => vw.url === activatedUrlKey);
|
||||
}
|
||||
|
||||
setActive(enteringView: RouteView): Promise<StackEvent> {
|
||||
@ -95,15 +91,15 @@ export class StackController {
|
||||
}
|
||||
|
||||
const views = this.insertView(enteringView, direction);
|
||||
return this.wait(async () => {
|
||||
await this.transition(enteringView, leavingView, animation, this.canGoBack(1), false);
|
||||
await cleanupAsync(enteringView, views, viewsSnapshot, this.location);
|
||||
return {
|
||||
enteringView,
|
||||
direction,
|
||||
animation,
|
||||
tabSwitch
|
||||
};
|
||||
return this.wait(() => {
|
||||
return this.transition(enteringView, leavingView, animation, this.canGoBack(1), false)
|
||||
.then(() => cleanupAsync(enteringView, views, viewsSnapshot, this.location))
|
||||
.then(() => ({
|
||||
enteringView,
|
||||
direction,
|
||||
animation,
|
||||
tabSwitch
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
@ -138,13 +134,12 @@ export class StackController {
|
||||
});
|
||||
}
|
||||
|
||||
async startBackTransition() {
|
||||
startBackTransition() {
|
||||
const leavingView = this.activeView;
|
||||
if (leavingView) {
|
||||
const views = this.getStack(leavingView.stackId);
|
||||
const enteringView = views[views.length - 2];
|
||||
enteringView.ref.changeDetectorRef.reattach();
|
||||
await this.wait(() => {
|
||||
return this.wait(() => {
|
||||
return this.transition(
|
||||
enteringView, // entering view
|
||||
leavingView, // leaving view
|
||||
@ -154,6 +149,7 @@ export class StackController {
|
||||
);
|
||||
});
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
endBackTransition(shouldComplete: boolean) {
|
||||
@ -189,7 +185,7 @@ export class StackController {
|
||||
return this.views.slice();
|
||||
}
|
||||
|
||||
private async transition(
|
||||
private transition(
|
||||
enteringView: RouteView | undefined,
|
||||
leavingView: RouteView | undefined,
|
||||
direction: 'forward' | 'back' | undefined,
|
||||
@ -198,7 +194,13 @@ export class StackController {
|
||||
) {
|
||||
if (this.skipTransition) {
|
||||
this.skipTransition = false;
|
||||
return;
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
if (enteringView) {
|
||||
enteringView.ref.changeDetectorRef.reattach();
|
||||
}
|
||||
if (leavingView) {
|
||||
leavingView.ref.changeDetectorRef.detach();
|
||||
}
|
||||
const enteringEl = enteringView ? enteringView.element : undefined;
|
||||
const leavingEl = leavingView ? leavingView.element : undefined;
|
||||
@ -209,15 +211,15 @@ export class StackController {
|
||||
containerEl.appendChild(enteringEl);
|
||||
}
|
||||
|
||||
await containerEl.componentOnReady();
|
||||
await containerEl.commit(enteringEl, leavingEl, {
|
||||
return this.zone.runOutsideAngular(() => containerEl.commit(enteringEl, leavingEl, {
|
||||
deepWait: true,
|
||||
duration: direction === undefined ? 0 : undefined,
|
||||
direction,
|
||||
showGoBack,
|
||||
progressAnimation
|
||||
});
|
||||
}));
|
||||
}
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
private async wait<T>(task: () => Promise<T>): Promise<T> {
|
||||
@ -245,7 +247,6 @@ function cleanup(activeRoute: RouteView, views: RouteView[], viewsSnapshot: Rout
|
||||
.forEach(destroyView);
|
||||
|
||||
views.forEach(view => {
|
||||
|
||||
/**
|
||||
* In the event that a user navigated multiple
|
||||
* times in rapid succession, we want to make sure
|
||||
|
Reference in New Issue
Block a user