[FIX] component: hooks mounted/willUnmount called in correct order

The issue was with parent/child relationship.  It is not intuitive to
me, but the mounted hook should be called first on the children, and
then on the parent.  willUnmount hooks is the opposite.

closes #63
This commit is contained in:
Géry Debongnie
2019-04-26 16:20:50 +02:00
parent b44f274e37
commit 005b727328
2 changed files with 80 additions and 75 deletions
+52 -45
View File
@@ -219,28 +219,38 @@ export class Component<
target.appendChild(this.el!);
if (document.body.contains(target)) {
this._visitSubTree(w => {
if (!w.__owl__.isMounted && this.el!.contains(w.el)) {
w.__owl__.isMounted = true;
w.mounted();
return true;
}
return false;
});
this._callMounted();
}
}
_callMounted() {
const children = this.__owl__.children;
for (let id in children) {
const comp = children[id];
if (!comp.__owl__.isMounted && this.el!.contains(comp.el)) {
comp._callMounted();
}
}
this.__owl__.isMounted = true;
this.mounted();
}
_callWillUnmount() {
this.willUnmount();
this.__owl__.isMounted = false;
const children = this.__owl__.children;
for (let id in children) {
const comp = children[id];
if (comp.__owl__.isMounted) {
comp._callWillUnmount();
}
}
}
unmount() {
if (this.el) {
this._visitSubTree(w => {
if (w.__owl__.isMounted) {
w.willUnmount();
w.__owl__.isMounted = false;
return true;
}
return false;
});
this.el.remove();
if (this.__owl__.isMounted) {
this._callWillUnmount();
this.el!.remove();
}
}
@@ -260,27 +270,34 @@ export class Component<
destroy() {
if (!this.__owl__.isDestroyed) {
for (let id in this.__owl__.children) {
this.__owl__.children[id].destroy();
const el = this.el;
this._destroy();
if (el) {
el.remove();
}
if (this.__owl__.isMounted) {
this.willUnmount();
}
if (this.el) {
this.el.remove();
this.__owl__.isMounted = false;
delete this.__owl__.vnode;
}
if (this.__owl__.parent) {
let id = this.__owl__.id;
delete this.__owl__.parent.__owl__.children[id];
this.__owl__.parent = null;
}
this.clear();
this.__owl__.isDestroyed = true;
}
}
_destroy() {
const isMounted = this.__owl__.isMounted;
if (isMounted) {
this.willUnmount();
this.__owl__.isMounted = false;
}
const children = Object.values(this.__owl__.children);
for (let child of children) {
child._destroy();
}
if (this.__owl__.parent) {
let id = this.__owl__.id;
delete this.__owl__.parent.__owl__.children[id];
this.__owl__.parent = null;
}
this.clear();
this.__owl__.isDestroyed = true;
delete this.__owl__.vnode;
}
shouldUpdate(nextProps: Props): boolean {
return true;
}
@@ -412,16 +429,6 @@ export class Component<
}
}
_visitSubTree(callback: (w: Component<T, any, any>) => boolean) {
const shouldVisitChildren = callback(this);
if (shouldVisitChildren) {
const children = this.__owl__.children;
for (let id in children) {
children[id]._visitSubTree(callback);
}
}
}
_observeState() {
if (this.state) {
this.__owl__.observer = new Observer();