mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-10 00:27:41 +08:00
fix(router): change detection for componentProps
This commit is contained in:
2
core/src/components.d.ts
vendored
2
core/src/components.d.ts
vendored
@ -4685,7 +4685,7 @@ declare global {
|
||||
/**
|
||||
* Used internaly by `ion-router` to know when this route did change.
|
||||
*/
|
||||
'onIonRouteDataChanged'?: (event: CustomEvent) => void;
|
||||
'onIonRouteDataChanged'?: (event: CustomEvent<any>) => void;
|
||||
/**
|
||||
* Relative path that needs to match in order for this route to apply.
|
||||
*/
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, Event, Prop } from '@stencil/core';
|
||||
import { Component, Event, Prop, Watch } from '@stencil/core';
|
||||
import { EventEmitter } from 'ionicons/dist/types/stencil.core';
|
||||
|
||||
@Component({
|
||||
@ -28,7 +28,33 @@ export class Route {
|
||||
/**
|
||||
* Used internaly by `ion-router` to know when this route did change.
|
||||
*/
|
||||
@Event() ionRouteDataChanged: EventEmitter;
|
||||
@Event() ionRouteDataChanged: EventEmitter<any>;
|
||||
|
||||
@Watch('url')
|
||||
@Watch('component')
|
||||
onUpdate(newValue: any) {
|
||||
this.ionRouteDataChanged.emit(newValue);
|
||||
}
|
||||
|
||||
@Watch('componentProps')
|
||||
onComponentProps(newValue: any, oldValue: any) {
|
||||
if (newValue === oldValue) {
|
||||
return;
|
||||
}
|
||||
const keys1 = newValue ? Object.keys(newValue) : [];
|
||||
const keys2 = oldValue ? Object.keys(oldValue) : [];
|
||||
if (keys1.length !== keys2.length) {
|
||||
this.onUpdate(newValue);
|
||||
return;
|
||||
}
|
||||
for (let i = 0; i < keys1.length; i++) {
|
||||
const key = keys1[i];
|
||||
if (newValue[key] !== oldValue[key]) {
|
||||
this.onUpdate(newValue);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
this.ionRouteDataChanged.emit();
|
||||
@ -36,7 +62,4 @@ export class Route {
|
||||
componentDidUnload() {
|
||||
this.ionRouteDataChanged.emit();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
this.ionRouteDataChanged.emit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,43 +32,41 @@ export class Router {
|
||||
componentDidLoad() {
|
||||
this.init = true;
|
||||
console.debug('[ion-router] router did load');
|
||||
this.onRedirectChanged(undefined);
|
||||
this.onRoutesChanged(undefined);
|
||||
|
||||
const tree = readRoutes(this.el);
|
||||
this.routes = flattenRouterTree(tree);
|
||||
this.redirects = readRedirects(this.el);
|
||||
this.writeNavStateRoot(this.getPath(), RouterDirection.None);
|
||||
}
|
||||
|
||||
@Listen('ionRouteRedirectChanged')
|
||||
protected onRedirectChanged(ev: Event) {
|
||||
protected onRedirectChanged(ev: CustomEvent) {
|
||||
if (!this.init) {
|
||||
return;
|
||||
}
|
||||
if (ev) {
|
||||
console.debug('[ion-router] route data changed', ev.target);
|
||||
}
|
||||
console.debug('[ion-router] redirect data changed', ev.target);
|
||||
this.redirects = readRedirects(this.el);
|
||||
}
|
||||
|
||||
@Listen('ionRouteDataChanged')
|
||||
protected onRoutesChanged(ev: Event) {
|
||||
protected onRoutesChanged(ev: CustomEvent) {
|
||||
if (!this.init) {
|
||||
return;
|
||||
}
|
||||
const tree = readRoutes(this.el);
|
||||
this.routes = flattenRouterTree(tree);
|
||||
console.debug('[ion-router] route data changed', ev.target, ev.detail);
|
||||
|
||||
// schedule write
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
this.timer = undefined;
|
||||
}
|
||||
if (ev) {
|
||||
console.debug('[ion-router] route data changed', ev.target);
|
||||
this.timer = setTimeout(() => {
|
||||
this.timer = undefined;
|
||||
this.writeNavStateRoot(this.getPath(), RouterDirection.None);
|
||||
});
|
||||
} else {
|
||||
this.timer = setTimeout(() => {
|
||||
this.timer = undefined;
|
||||
console.debug('[ion-router] data changed -> update nav');
|
||||
this.writeNavStateRoot(this.getPath(), RouterDirection.None);
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
@Listen('window:popstate')
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { NavOutlet, NavOutletElement, RouteChain, RouteID, RouterDirection } from './interfaces';
|
||||
|
||||
export async function writeNavState(root: HTMLElement|undefined, chain: RouteChain|null, direction: RouterDirection, index: number): Promise<boolean> {
|
||||
export async function writeNavState(root: HTMLElement|undefined, chain: RouteChain|null, direction: RouterDirection, index: number, changed = false): Promise<boolean> {
|
||||
// find next navigation outlet in the DOM
|
||||
const outlet = searchNavNode(root);
|
||||
|
||||
@ -17,10 +17,11 @@ export async function writeNavState(root: HTMLElement|undefined, chain: RouteCha
|
||||
// this means nested outlets will not animate
|
||||
if (result.changed) {
|
||||
direction = RouterDirection.None;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// recursivelly set nested outlets
|
||||
const changed = await writeNavState(result.element, chain, direction, index + 1);
|
||||
changed = await writeNavState(result.element, chain, direction, index + 1, changed);
|
||||
|
||||
// once all nested outlets are visible let's make the parent visible too,
|
||||
// using markVisible prevents flickering
|
||||
|
||||
Reference in New Issue
Block a user