[On-Demand Definitions] Initial draft
This is an initial draft of the On-Demand Definitions proposal: A protocol for defining custom elements when needed without relying on top-level side-effects.
TL;DR:
**Problems:**
1. It is very easy to forget a critical import and use a custom element before it is defined.
```javascript
document.querySelector('my-element').doSomething();
// ^ `<my-element>` may or may not be defined.
```
2. Defining elements as adjacent top-level side-effects to the class definition prevents tree shaking.
3. Side-effectful imports are bad<sup>TM</sup>.
4. Forgetting an import on a custom element leads to a file ordering hazard.
**Proposal**:
Instead of writing `customElements.define('my-element', MyElement)` as an adjacent top-level side-effect, put it in a static `define` property of the class:
```javascript
export class MyElement extends HTMLElement {
static define() {
// Check if the tag name was already defined by another class.
const existing = customElements.get('my-element');
if (existing) {
if (existing === MyElement) {
return; // Already defined as the correct class, no-op.
} else {
throw new Error(`Tag name \`my-element\` already defined as \`${
existing.name}\`.`);
}
}
customElements.define('my-element', MyElement);
}
}
```
This removes top-level side-effects making the element tree-shakable. Any consumers of this class can call `MyElement.define()` to ensure it is defined before they attempt to use it. This decentralizes the process of defining a custom element and more closely couples the definition with its specific usages.
合并状态:未合并 关闭于 2025-01-30 17 条评论