feat: new attachEffect utility
This commit is contained in:
parent
aa30c99487
commit
a9b9ada5e3
3 changed files with 53 additions and 20 deletions
|
@ -1,14 +1,22 @@
|
|||
// @ts-check
|
||||
import WebComponent from "../src/WebComponent.js";
|
||||
// import { attachEffect } from "../src/attach-effect.js";
|
||||
import { attachEffect } from "../src/attach-effect.js";
|
||||
|
||||
export class Counter extends WebComponent {
|
||||
static properties = ["count"];
|
||||
onInit() {
|
||||
this.props.count = 0;
|
||||
this.onclick = () => ++this.props.count;
|
||||
// attachEffect(this.props, 'count', console.log);
|
||||
attachEffect(
|
||||
this.props.count,
|
||||
(count) => console.log(count)
|
||||
);
|
||||
}
|
||||
|
||||
afterViewInit(){
|
||||
attachEffect(this.props.count, (count) => console.log(count + 100));
|
||||
}
|
||||
|
||||
get template() {
|
||||
return `<button id="btn">${this.props.count}</button>`;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ export class WebComponent extends HTMLElement {
|
|||
* Read-only property containing camelCase counterparts of observed attributes.
|
||||
* @see https://www.npmjs.com/package/web-component-base#prop-access
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset
|
||||
* @typedef {{[name: string]: any}} PropStringMap
|
||||
* @type {PropStringMap}
|
||||
*/
|
||||
get props() {
|
||||
|
@ -53,11 +52,7 @@ export class WebComponent extends HTMLElement {
|
|||
|
||||
/**
|
||||
* Triggered when an attribute value changes
|
||||
* @param {{
|
||||
* property: string,
|
||||
* previousValue: any,
|
||||
* currentValue: any
|
||||
* }} changes
|
||||
* @param {Changes} changes
|
||||
*/
|
||||
onChanges(changes) {}
|
||||
|
||||
|
@ -125,7 +120,11 @@ export class WebComponent extends HTMLElement {
|
|||
}
|
||||
};
|
||||
|
||||
#handler(setter, typeMap) {
|
||||
#effectsMap = {};
|
||||
|
||||
#handler(setter, meta) {
|
||||
const effectsMap = meta.#effectsMap;
|
||||
const typeMap = meta.#typeMap;
|
||||
const getKebab = (str) => {
|
||||
return str.replace(
|
||||
/[A-Z]+(?![a-z])|[A-Z]/g,
|
||||
|
@ -141,14 +140,25 @@ export class WebComponent extends HTMLElement {
|
|||
typeMap[prop] = typeof value;
|
||||
}
|
||||
|
||||
if (oldValue !== value) {
|
||||
if (value.attach === "effect") {
|
||||
if (!effectsMap[prop]) {
|
||||
effectsMap[prop] = [];
|
||||
}
|
||||
effectsMap[prop].push(value.callback);
|
||||
} else if (oldValue !== value) {
|
||||
obj[prop] = value;
|
||||
effectsMap[prop]?.forEach((f) => f(value));
|
||||
const kebab = getKebab(prop);
|
||||
setter(kebab, value);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
get(obj, prop) {
|
||||
Object.getPrototypeOf(obj[prop]).proxy = meta.#props;
|
||||
Object.getPrototypeOf(obj[prop]).prop = prop;
|
||||
return obj[prop];
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -156,13 +166,19 @@ export class WebComponent extends HTMLElement {
|
|||
if (!this.#props) {
|
||||
this.#props = new Proxy(
|
||||
{},
|
||||
this.#handler(
|
||||
(key, value) => this.setAttribute(key, value),
|
||||
this.#typeMap
|
||||
)
|
||||
this.#handler((key, value) => this.setAttribute(key, value), this)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default WebComponent;
|
||||
|
||||
/**
|
||||
* @typedef {{
|
||||
* property: string,
|
||||
* previousValue: any,
|
||||
* currentValue: any
|
||||
* }} Changes
|
||||
* @typedef {{[name: string]: any}} PropStringMap
|
||||
*/
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
export function attachEffect(proxy, prop, callback) {
|
||||
proxy[prop] = {
|
||||
attach: 'effect',
|
||||
callback
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @typedef { import('./WebComponent.js').Changes} Changes
|
||||
* @typedef { import('./WebComponent.js').PropStringMap} PropStringMap
|
||||
* @param {Object} obj
|
||||
* @param {(newValue: any) => void} callback
|
||||
*/
|
||||
export function attachEffect(obj, callback) {
|
||||
const { proxy, prop } = Object.getPrototypeOf(obj);
|
||||
|
||||
proxy[prop] = {
|
||||
attach: "effect",
|
||||
callback,
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue