1.8 KiB
status, date
| status | date |
|---|---|
| implemented | 2026-03-05 |
Destroy Lifecycle: DestroyMixin
Decision
The deferred destruction lifecycle is implemented as a composable mixin (DestroyMixin)
exported from @videojs/element, rather than being added directly to ReactiveElement.
ReactiveElement stays structurally compatible with Lit's ReactiveElement.
Architecture
@videojs/utils/dom → deferFrames() composable utility
@videojs/element → DestroyMixin(HTMLElement) — generic, works with any base
@videojs/html → MediaElement = DestroyMixin(ReactiveElement) + hostDestroyed()
@videojs/core → HlsCustomMedia = DestroyMixin(HTMLElement) via CustomMediaMixin
DestroyMixin
Adds destroyed, destroy(), destroyCallback(), deferred 2-rAF scheduling on
disconnect, cancel on reconnect, and keep-alive attribute support. Works with any
HTMLElement subclass.
MediaElement
Composes DestroyMixin(ReactiveElement) and bridges destroyCallback() to
hostDestroyed() on reactive controllers. Also guards performUpdate() when destroyed.
HlsCustomMedia
Uses DestroyMixin(HTMLElement) as the base for CustomMediaMixin. The DelegateMedia
class (from DelegateMixin) overrides destroyCallback() to call
this.#delegate.destroy?.(), which destroys the HLS engine.
Why a Mixin
ReactiveElementstays Lit-compatible (no added public surface)- Works with
HTMLElementdirectly (noReactiveElementrequired for custom media elements) - Composable — any element can opt in
Alternatives Considered
- Put everything on
ReactiveElement— Simpler (direct#controllersaccess), but breaks Lit structural compat. Rejected. - Separate
MediaElementclass without mixin — Doesn't compose withCustomMediaMixin(HTMLElement)for custom media elements. Rejected.