fix(router): change detection for componentProps

This commit is contained in:
Manu Mtz.-Almeida
2018-03-27 00:57:50 +02:00
parent ffaec1661a
commit a718f7e1e3
4 changed files with 45 additions and 23 deletions

View File

@ -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.
*/

View File

@ -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();
}
}

View File

@ -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')

View File

@ -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