commit 536345453a3e94c90795dc3b86522f4db65e142f
parent 1f57502fb64495c1420f8aed15ee2b47a9799b1b
Author: finwo <finwo@pm.me>
Date: Thu, 29 Oct 2020 11:41:00 +0100
Basic data-binding
Diffstat:
2 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/index.js b/index.js
@@ -22,7 +22,34 @@
if ('object' !== typeof obj) return false;
if (Array.isArray(obj)) return false;
return true;
- }
+ },
+ observable(obj, callback, prefix = '') {
+ if (!util.isObject(obj)) {
+ throw new Error(`Object is not an object, got: ${obj}`);
+ }
+ if ('function' !== typeof callback) {
+ throw new Error(`Callback is not a function, got: ${callback}`);
+ }
+ return new Proxy(obj, {
+ set(target, name, value, receiver) {
+ var oldVal = target[name];
+ if (oldVal === value) return;
+ let type = name in target ? 'update' : 'add';
+ const record = { name, type, object: target };
+ if (type == 'update') record.oldValue = target[name];
+ target[name] = Object(value) === value ? util.observable(value,callback,`${prefix}${name}.`) : value;
+ callback([record]);
+ return true;
+ },
+ deleteProperty(target, name, value) {
+ if (!(name in target)) return;
+ const record = { name, type: 'delete', object: target, oldValue: target[name] };
+ delete target[name];
+ callback([record]);
+ return true;
+ },
+ });
+ },
};
// Override configs
@@ -70,6 +97,7 @@
constructor() {
super();
+ // Initial state
this.state = {};
// Initialize shadow root
@@ -82,20 +110,21 @@
// Run component code
(new Function(code)).call(this);
- this.root.innerHTML = this.render();
// Load dependencies
if (this.dependencies) {
dependencies.forEach(fwebc.load);
}
-
+ // Start observing state & initial rendering
+ this.state = util.observable(this.state, this.render.bind(this));
+ this.render();
}
render() {
const fn = new Function(...Object.keys(this.state), "return `"+ template.replace(/`/g,'\\`') + "`;");
- return fn(...Object.values(this.state));
- }
+ try { this.root.innerHTML = fn(...Object.values(this.state)); } catch(e) { console.error(e); }
+ };
update(data) {
Object.entries(data)
@@ -103,7 +132,6 @@
this.state[key] = util.isObject(this.state[key]) &&
util.isObject(value) ? {...this.state[key], ...value} : value;
});
- this.root.innerHTML = this.render();
}
});
diff --git a/test/partial/my-app.tag b/test/partial/my-app.tag
@@ -7,10 +7,10 @@
}
</style>
<script>
- this.state = {
+ this.update({
n: 0,
- subject: 'WORD',
- };
+ subject: 'word',
+ });
setInterval(() => {
this.update({
n: this.state.n + 1,