mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 01:52:19 +08:00
fix(angular): ngOnDestroy runs inside angular zone (#24949)
Resolves #22571
This commit is contained in:
@ -139,7 +139,7 @@ export class StackController {
|
|||||||
enteringView.ref.changeDetectorRef.reattach();
|
enteringView.ref.changeDetectorRef.reattach();
|
||||||
|
|
||||||
return this.transition(enteringView, leavingView, animation, this.canGoBack(1), false, animationBuilder)
|
return this.transition(enteringView, leavingView, animation, this.canGoBack(1), false, animationBuilder)
|
||||||
.then(() => cleanupAsync(enteringView, views, viewsSnapshot, this.location))
|
.then(() => cleanupAsync(enteringView, views, viewsSnapshot, this.location, this.zone))
|
||||||
.then(() => ({
|
.then(() => ({
|
||||||
enteringView,
|
enteringView,
|
||||||
direction,
|
direction,
|
||||||
@ -201,7 +201,7 @@ export class StackController {
|
|||||||
this.skipTransition = true;
|
this.skipTransition = true;
|
||||||
this.pop(1);
|
this.pop(1);
|
||||||
} else if (this.activeView) {
|
} else if (this.activeView) {
|
||||||
cleanup(this.activeView, this.views, this.views, this.location);
|
cleanup(this.activeView, this.views, this.views, this.location, this.zone);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,11 +294,17 @@ export class StackController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const cleanupAsync = (activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[], location: Location) => {
|
const cleanupAsync = (
|
||||||
|
activeRoute: RouteView,
|
||||||
|
views: RouteView[],
|
||||||
|
viewsSnapshot: RouteView[],
|
||||||
|
location: Location,
|
||||||
|
zone: NgZone
|
||||||
|
) => {
|
||||||
if (typeof (requestAnimationFrame as any) === 'function') {
|
if (typeof (requestAnimationFrame as any) === 'function') {
|
||||||
return new Promise<void>((resolve) => {
|
return new Promise<void>((resolve) => {
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
cleanup(activeRoute, views, viewsSnapshot, location);
|
cleanup(activeRoute, views, viewsSnapshot, location, zone);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -306,8 +312,18 @@ const cleanupAsync = (activeRoute: RouteView, views: RouteView[], viewsSnapshot:
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanup = (activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[], location: Location) => {
|
const cleanup = (
|
||||||
viewsSnapshot.filter((view) => !views.includes(view)).forEach(destroyView);
|
activeRoute: RouteView,
|
||||||
|
views: RouteView[],
|
||||||
|
viewsSnapshot: RouteView[],
|
||||||
|
location: Location,
|
||||||
|
zone: NgZone
|
||||||
|
) => {
|
||||||
|
/**
|
||||||
|
* Re-enter the Angular zone when destroying page components. This will allow
|
||||||
|
* lifecycle events (`ngOnDestroy`) to be run inside the Angular zone.
|
||||||
|
*/
|
||||||
|
zone.run(() => viewsSnapshot.filter((view) => !views.includes(view)).forEach(destroyView));
|
||||||
|
|
||||||
views.forEach((view) => {
|
views.forEach((view) => {
|
||||||
/**
|
/**
|
||||||
|
@ -20,6 +20,12 @@ describe('Nested Outlet', () => {
|
|||||||
cy.ionPageVisible('app-nested-outlet-page2');
|
cy.ionPageVisible('app-nested-outlet-page2');
|
||||||
|
|
||||||
cy.get('ion-router-outlet ion-router-outlet app-nested-outlet-page2 h1').should('have.text', 'Nested page 2');
|
cy.get('ion-router-outlet ion-router-outlet app-nested-outlet-page2 h1').should('have.text', 'Nested page 2');
|
||||||
|
|
||||||
|
cy.get('#goto-nested-page1').click();
|
||||||
|
cy.ionPageVisible('app-nested-outlet-page');
|
||||||
|
|
||||||
|
cy.get('#goto-nested-page2').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-nested-outlet-page',
|
selector: 'app-nested-outlet-page',
|
||||||
templateUrl: './nested-outlet-page.component.html',
|
templateUrl: './nested-outlet-page.component.html',
|
||||||
})
|
})
|
||||||
export class NestedOutletPageComponent {
|
export class NestedOutletPageComponent implements OnDestroy, OnInit {
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
NgZone.assertInAngularZone();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
NgZone.assertInAngularZone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
<ion-content>
|
<ion-content>
|
||||||
<h1>Nested page 2</h1>
|
<h1>Nested page 2</h1>
|
||||||
<p>
|
<p>
|
||||||
<ion-button routerLink="/nested-outlet/page">Go To FIRST</ion-button>
|
<ion-button routerLink="/nested-outlet/page" id="goto-nested-page1">Go To FIRST</ion-button>
|
||||||
</p>
|
</p>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
@ -1,8 +1,16 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-nested-outlet-page2',
|
selector: 'app-nested-outlet-page2',
|
||||||
templateUrl: './nested-outlet-page2.component.html',
|
templateUrl: './nested-outlet-page2.component.html',
|
||||||
})
|
})
|
||||||
export class NestedOutletPage2Component {
|
export class NestedOutletPage2Component implements OnDestroy, OnInit {
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
NgZone.assertInAngularZone();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
NgZone.assertInAngularZone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user