diff --git a/examples/jdom-template/main.js b/examples/jdom-template/main.js index d213005..52097cf 100644 --- a/examples/jdom-template/main.js +++ b/examples/jdom-template/main.js @@ -1,4 +1,28 @@ -import { $, state, computed, html } from '../../index.js'; +import { $, $r, state, computed, html, JDOMComponent } from '../../index.js'; + +class Test2 extends JDOMComponent { + test = state('Test2') + + constructor() { + super() + } + render() { + console.log(this.test) + return html`a: ${this.test}` + } +} +$r('test-app', Test2) + +class Test { + image = state('Test1') + create(){ + html`<${Test2} test=${this.image} /> `.appendTo(document.body); + } +} + +new Test().create() + + const tasks = state([]); diff --git a/package.json b/package.json index d365eeb..ba4845e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jdomjs", - "version": "3.1.11", + "version": "3.1.12", "description": "A wrapper for query selector and html elements", "main": "./index.js", "types": "./types/index.d.ts", diff --git a/src/Hook.js b/src/Hook.js index cf01d78..8c8ab73 100644 --- a/src/Hook.js +++ b/src/Hook.js @@ -9,6 +9,10 @@ export default class Hook { #destroyed = false #alreadyProxied = false + static TRACKING = [] + static IS_TRACKING = false + + /** * @param {T} value */ @@ -94,6 +98,7 @@ export default class Hook { * @return {T} */ get value() { + Hook.track(this) return this._value } @@ -104,8 +109,10 @@ export default class Hook { dispatchListener(oldVal) { for (let listener of this.listeners) { - if (listener.call(this, this._value, oldVal) === true) - break + try { + if (listener.call(this, this._value, oldVal) === true) + break + } catch (e) {} } } @@ -128,4 +135,32 @@ export default class Hook { toString() { return `${this.value}` } + + /** + * @param {Hook} hook + */ + static track(hook) { + if (Hook.IS_TRACKING) { + Hook.TRACKING.push(hook) + } + } + + static enableTracking() { + Hook.IS_TRACKING = true + } + static disableTracking() { + Hook.IS_TRACKING = false + Hook.clearTracked() + } + + /** + * @return {Hook[]} + */ + static getTracked() { + return Hook.TRACKING + } + + static clearTracked() { + Hook.TRACKING = [] + } } \ No newline at end of file diff --git a/src/decorators.ts b/src/decorators.ts index 9982205..cf8d2a5 100644 --- a/src/decorators.ts +++ b/src/decorators.ts @@ -21,7 +21,7 @@ export function State() { } } -export function Computed(dependencies: string[] | ((target: any) => Hook[])) { +export function Computed(dependencies: string[] | ((target: any) => Hook[])) { return function(target: any, key: string) { const func = target[key]; diff --git a/src/hooks.js b/src/hooks.js index 41d5427..00e32dc 100644 --- a/src/hooks.js +++ b/src/hooks.js @@ -10,18 +10,32 @@ export function state(initialValue) { } /** + * If dependencies is not given, the dependencies will be automatically seletected + * * @template T * @param {function(): T} callable - * @param {Hook[]} dependencies + * @param {Hook[]|undefined} dependencies * @return {Hook} */ -export function computed(callable, dependencies = []) { +export function computed(callable, dependencies = undefined) { const hook = new Hook(callable()) - for (let dependency of dependencies) { - dependency.listeners.push(() => { - hook.value = callable() - }) + if (dependencies === undefined) { + Hook.enableTracking() + callable() + + for (const trackedElement of Hook.getTracked()) { + trackedElement.addListener(() => { + hook.value = callable() + }) + } + Hook.disableTracking() + } else { + for (let dependency of dependencies) { + dependency.listeners.push(() => { + hook.value = callable() + }) + } } return hook diff --git a/src/template/TemplateDOMAdapter.js b/src/template/TemplateDOMAdapter.js index 9bd41a4..5c4628f 100644 --- a/src/template/TemplateDOMAdapter.js +++ b/src/template/TemplateDOMAdapter.js @@ -144,8 +144,14 @@ export default class TemplateDOMAdapter { if (usingJDOMComponent) { if (key.endsWith('.attr')) { elem.setAttribute(key.replace('.attr', ''), value) + } else if (key.endsWith('.unhook')) { + elem[key] = value + } else if (elem[key] instanceof Hook) { + elem[key].value = value + } else { + elem[key] = value } - elem[key] = value + return } elem.setAttribute(key, value)