Custom Modules
Events
Safe event bus patterns for subscribing, emitting, and naming custom-module channels.
Events
this.events is the shared event bus available to custom modules. Use it to subscribe to runtime signals and to publish your own channels without tightly coupling modules together.
Typical Uses
- subscribe to global lifecycle events in
onSubscribe(...) - emit object-scoped output channels
- bridge one runtime signal into a more useful custom-module event
Subscribe Safely
The usual pattern is:
override onSubscribe(): void {
this.events.on('scroll:start', this.onScrollStartEvent);
}
override onUnsubscribe(): void {
this.events.off('scroll:start', this.onScrollStartEvent);
}
Keep subscription and unsubscription symmetrical.
Emit Object-Scoped Events
When publishing per-object channels, prefer getObjectEventName(...) over manual string building.
this.events.emit(this.getObjectEventName(object, 'object:rotate-progress'), { progress, rotation });
That keeps naming consistent and avoids repeated string work in hot paths.
What To Emit
Good custom-module events usually represent one of these:
- computed output state
- phase change
- object-scoped interaction data
Examples:
object:rotate-progress:<id>object:mask-shift:<id>module:ready
What Not To Do
- do not emit noisy per-frame payloads unless consumers really need them
- do not invent unclear names that overlap with existing built-in channels
- do not rely on undocumented internal channels unless you explicitly control both sides
Naming Guidance
Prefer names that make scope obvious:
- global channel:
feature:ready - object-scoped channel:
object:feature:<id>
If your custom module mirrors built-in module style, consumers will understand it faster.
Cross-Module Communication
The event bus is useful when:
- direct imports would create tighter coupling
- one module should react to another module's output
- DOM wiring would be noisier than one scoped event
But if two modules are effectively one feature, keep the design honest. Sometimes one module is cleaner than an event-driven split.