Reactive Web Components 1kb - Library.js
by patrickml
HTML
<!DOCTYPE html>
<html>
<body>
<h1>Testing</h1>
<proxy-provider store="users">
<button is="add-user-button"></button>
</proxy-provider>
<proxy-provider store="users" subscribe>
<user-list></user-list>
</proxy-provider>
</body>
</html>
JavaScript
const ProxyStore = (values={}, options={}) => new Proxy(
{
__registry: {},
subscribe: function(key, fn) {
this.__registry[key] = [...(this.__registry[key] || []), fn];
},
unsubscribe: function(key, fn) {
this.__registry[key] = this.__registry[key].filter(fn);
},
...values,
},
{
get: function(target, name, receiver) {
return Reflect.get(target, name, receiver);
},
set: function(target, name, value, receiver) {
Reflect.set(target, name, value, receiver);
target.__registry[name].forEach(fn => fn());
return true;
},
...options,
}
);
const store = ProxyStore({ users: [] });
const NodeOf = (type) => (
class Node extends type {
constructor() { super(); }
componentDidRender() {}
componentDidMount() {}
componentDidUnmount() {}
connectedCallback() {
this.componentDidMount();
this.renderNode();
}
disconnectedCallback() {
this.componentDidUnmount();
}
renderNode() {
let html = this.render();
if (Array.isArray(html)) {
html = html.join('');
}
if (this._shadow) this._shadow.innerHTML = html;
else this.innerHTML = html;
this.componentDidRender();
}
}
)
const Node = NodeOf(HTMLElement);
class ProxyNode extends Node {
set data(data) {
this._data = data;
this.renderNode();
}
get data() {
return this._data;
}
}
class ProxyProvider extends HTMLElement {
get subscribe() { return this.hasAttribute('subscribe'); }
get storeKey() { return this.getAttribute('store'); }
get data() { return store[this.storeKey]; }
set data(value) { return store[this.storeKey] = value; }
_subscribe() {
store.subscribe(this.storeKey,...