Контроль Event.eventPhase в пользовательских деревьях
Описание
Вот есть класс для событий в JavaScript - Event. И так же другой класс принимающий эти события - EventTarget.
Создал у себя класс наследовав EventTarget:
class Entity extends EventTarget {
name: string;
parent: Entity;
children: Entity[];
}
И собственно потом создаю обычное дерево из этого класса. Так как у класса Event есть функция погружения (capturing) и всплывания (bubbling) думал переписать dispatchEvent так, чтобы и у моего дерева выполнилось погружение и всплытие события.
Ну, собственно как-то так:
class Entity extends EventTarget {
name: string;
#parent: Entity | null = null;
get parent(): Entity {
return this.#parent ?? (() => {
throw new ReferenceError(`Parent entity is null`);
})();
}
children: Entity[];
dispatchEvent(event: Event): boolean {
if (event.eventPhase === Event.CAPTURING_PHASE) {
try {
if (!this.parent.dispatchEvent(event)) return false;
} catch (error) { }
}
if (event.eventPhase === Event.AT_TARGET) {
if (!super.dispatchEvent(event)) return false;
}
if (event.eventPhase === Event.BUBBLING_PHASE) {
for (const child of this.children) {
if (!child.dispatchEvent(event)) return false;
}
}
return true;
}
}
Вопрос
Так вот свойство eventPhase всегда стоит на Event.NONE и это нельзя изменить, так как оно только для чтения.
Как я могу контролировать Event.eventPhase, чтобы реализовать погружение и всплытие в собственном дереве?
Пример
Пример максимально упрощён для легкого понимания.
const e1 = new Entity();
const e2 = new Entity();
e1.children.push(e2);
const e3 = new Entity();
e2.children.push(e3);
e1.addEventListener(`test`, (event) => {
console.log(`Event ${event.type} from e1 at phase ${event.eventPhase}`);
});
e3.addEventListener(`test`, (event) => {
console.log(`Event ${event.type} from e3 at phase ${event.eventPhase}`);
});
e2.dispatchEvent(new Event(`test`, { bubbles: true }));
При запуске должен выводится в консоль.
Event test from e1 at phase 1
Event test from e3 at phase 3