Add more examples to readme
This commit is contained in:
parent
bfb9b560ca
commit
ff0f7a96a7
1 changed files with 70 additions and 3 deletions
73
readme.md
73
readme.md
|
@ -2,6 +2,23 @@
|
|||
|
||||
A prototype for an alternative to custom elements.
|
||||
|
||||
```js
|
||||
// example.js
|
||||
import controllers from "controller-registry"
|
||||
|
||||
controllers.define("clickable", (element, detached) => {
|
||||
element.addEventListener("click", () => {
|
||||
alert("The element has been clicked!")
|
||||
}, detached)
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<script type="module" src="example.js"></script>
|
||||
|
||||
<button controller="clickable">Try clicking this button</button>
|
||||
```
|
||||
|
||||
## Concept
|
||||
|
||||
Similar to a custom element, a controller defines custom behaviours for HTML
|
||||
|
@ -26,13 +43,63 @@ Controllers can be registered under any name as either a callback which gets
|
|||
called when the controller is added to an element or a constructor which gets
|
||||
called with `new` and passed a revokable proxy to the element.
|
||||
|
||||
```js
|
||||
controllers.define("showcase", class ShowcaseController {
|
||||
constructor(element, detached) {
|
||||
this.method(element)
|
||||
// detached promise is passed here too for convenience,
|
||||
// but the `detached` method is the preferred place
|
||||
// to put cleanup code.
|
||||
}
|
||||
|
||||
method(element) {
|
||||
console.log("Calling method on:", element)
|
||||
}
|
||||
|
||||
detached(element) {
|
||||
// Cleanup if necessary
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
Note that only class controllers are given a revocable proxy: this is because
|
||||
their stateful nature and suitability for more complex handling makes them more
|
||||
likely candidates to retain references to the target past their detachment.
|
||||
|
||||
For complex function controllers, this can easily be done manually using
|
||||
`Proxy.revocable(element, {})`.
|
||||
|
||||
This behaviour might change in the future.
|
||||
|
||||
If the controller is a function, the second argument is a promise that resolves
|
||||
when the controller is removed again. This promise has an additional property
|
||||
`"signal"` which returns an `AbortSignal`. This means the promise can be passed
|
||||
directly as the third argument to `addEventListener` function calls.
|
||||
to the element when the controller is removed again. This promise has an
|
||||
additional property `"signal"` which returns an `AbortSignal`. This means the
|
||||
promise can be passed directly as the third argument to `addEventListener`
|
||||
function calls.
|
||||
|
||||
```js
|
||||
controllers.define("showcase", async (element, detached) => {
|
||||
console.log("Attached to element:", element)
|
||||
console.log("Detached promise:", detached)
|
||||
console.log("Detached signal:", detached.signal)
|
||||
element === await detached
|
||||
console.log("Detached from element:", element)
|
||||
}
|
||||
```
|
||||
|
||||
The registry also exposes a `list` function which, given an element, returns an
|
||||
object similar to a `DomTokenList` for easier management of the controller list.
|
||||
|
||||
The `controller` attribute is a space-separated list of controller names as
|
||||
registered in the registry.
|
||||
|
||||
## Interactions between controllers
|
||||
|
||||
There is no direct way for controllers to interact with each other, as they
|
||||
should be mostly independent.
|
||||
|
||||
When signalling is needed, events are the way to go; when data needs to be
|
||||
shared, the element's `dataset` or a more semantic attribute should be used.
|
||||
|
||||
For anything even more complex, a custom element or a higher level component
|
||||
framework might be the better solution.
|
||||
|
|
Loading…
Reference in a new issue