Based on #509, #662, and #663, I've released a standalone implementation of "Element Behaviors", published to NPM as element-behaviors.
I currently use Element Behaviors in Lume to implement various rendering behaviors for custom 3D elements, and I plan to use element behaviors to define mixable functionalities useful in interactive apps like 3D games or decorated web sites.
Additionally, I've implemented a "default behavior" system in Lume, on top of element-behaviors (not published as standalone yet) that makes it easy to define Custom Element classes that ship with default sets of behaviors, as well as makes it easy to add/remove behaviors in the same way that it is easy to add/remove classes with el.classList.add/remove
.
For all intents and purposes, this is an "entity-component" system, but in this case called "element behaviors" which avoids conflict with widely-used term "component" in the web these days.
Element behaviors allow us to add any number of functionalities ("behaviors") to any number of elements, using interfaces similar to Custom Elements, and a new has=""
attribute. See the README for more details, examples, and API.
This is an alternative to the is=""
attribute, where instead of using an is-a
design pattern we're using a has-a
design pattern which is less complicated and more flexible.
The first example from the README is on codepen:
https://codepen.io/trusktr/pen/3abb3ab634d1171954fb00fbc188b9e7.
Not shown in that demo, also apply any number of behaviors to any number of elements:
<div has="click-logger other-behavior" attribute-for-other="foo">one</div> <p has="click-logger some-action">two</p> <button has="click-logger other-behavior some-action" attribute-for-other="foo">three</button>mixin-like "element behaviors", without extending builtins
The idea uses a has=""
attribute to apply more than one behavior/functionality to an element (is=""
can only apply a single behavior/functionality to an element), using lifecycle methods similar to Custom Elements.
// define behaviors elementBehaviors.define('foo', class { // no inheritance necessary connectedCallback(el) { ... } disconnectedCallback(el) { ... } static get observedAttributes() { return ['some-attribute'] } attributeChangedCallback(el, attr, oldVal, newVal) { ... } }) elementBehaviors.define('bar', class { ... }) elementBehaviors.define('baz', class { ... })
<!-- apply any number of behaviors to any number of elements: --> <div has="bar baz"></div> <table> <tr has="foo baz" some-attribute="lorem"></tr> <!-- yay! --> </table> <button has="bar foo" some-attribute="ipsum"></button> <input has="foo bar baz" some-attribute="dolor"></input>
In a variety of cases, this has advantages over Custom Elements (with and without is=""
and):
table/tr
problem)is=""
!)Suppose we have an HTML app:
<div> <h1>my app</h1> <input ...></input> <button></button> </div>
With Custom Elements, we could enhance it like the following, but it requires changing the names of the elements, which can cause conflicts with CSS and JS code:
<awesome-layout> <h1>my app</h1> <awesome-input ...></awesome-input> <awesome-button></awesome-button> </awesome-layout>
With Element Behaviors, we can more easily add the functionality without modifying existing markup, CSS, or JS:
<div has="awesome-layout other-behavior"> <h1>my app</h1> <input has="awesome-input input-validator input-logger" ...></input> <button has="awesome-button particle-click-effect"></button> </div>
Of course, the implementation of a behavior that doesn't extend from the target element might require a different sort of implementation than a Custom Element that extends from the target element. Nothings perfect, and one way may be a little more work than the other way depending on scenario. But overall, the utility is improved (f.e. mix behaviors together, and some behaviors might even team up to do certain things when combined together on a single element), avoid strange parser problems, stay out of the way of existing CSS/JS, and more.
calebdwilliams, equinusocio, LasaleFamine, ruslan-kurchenko, AndyOGo and 10 moreLasaleFamine, asbjornu, AndyOGo, bakura10, Kaleidea and 1 more
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4