Skip to content

Base class

Every component extends Base. It carries the element, the live views over its markup, the lifecycle, the event conventions and the scheduling handles — and nothing else. Base knows nothing about services, view transitions or storage.

js
import { 
Base
} from '@studiometa/js-toolkit';
class
Component
extends
Base
{
static
config
= {
name
: 'Component',
}; }

Sections

The constructor

ts
new Base(el: HTMLElement)

Do not call it. The registry is the only code that constructs an instance, and an instance built by hand is not in the element's instance map, so nothing finds it and nothing unmounts it.

A component's own constructor is a legitimate place for field initializers, and two registrations belong there because they are instance-scoped rather than unmount-scoped:

js
class 
Slider
extends
Base
{
static
config
= {
name
: 'Slider',
components
: {} };
// Never released. Both die with the element.
api
= this.
$provide
(
Ctx
, {
goNext
: () => {} });
items
= this.
$watchChildren
('SliderItem');
}

Fixed properties

$el, $id, $options and $refs are fixed properties of the instance, not fields it happens to hold. They are defined non-writable in the constructor, so an assignment throws in a module rather than replacing what every other part of the framework reads.

readonly states it for a reader with a build step; the property descriptor states it for everyone else. They stay enumerable, so an instance still reads as one.

The typed surface

Base takes an optional props type with four optional keys — $el, $refs, $options and $emits. See TypeScript.

ts
import { 
Base
} from '@studiometa/js-toolkit';
class
Slider
extends
Base
<{
$refs
: {
next
: HTMLButtonElement };
$options
: {
speed
: number };
$emits
: {
goto
: {
index
: number };
stop
: void };
}> { static
config
= {
name
: 'Slider',
refs
: ['next'],
options
: {
speed
: {
type
:
Number
,
default
: 1 } },
}; }

MIT Licensed