Compare commits
3 commits
main
...
reactivity
Author | SHA1 | Date | |
---|---|---|---|
|
ef0b607e42 | ||
|
8e3aa4228c | ||
|
975cde8a31 |
3 changed files with 57 additions and 34 deletions
39
README.md
39
README.md
|
@ -1,3 +1,13 @@
|
|||
# `reactivity-test`
|
||||
|
||||
this branch is for testing out things related to making elements change in reaction to changes in data.
|
||||
|
||||
right now, functions passed to `json_as_html` will have an optional additional argument, that's a function. calling it with another function, will make it so that that other function is applied to the element returned from the first function (the one passed to `json_as_html`).
|
||||
|
||||
the demo uses this to create an event listener (in a tiny event system made for this), that modifies the contents of an element. the event is triggered by a button onclick just like it was previously.
|
||||
|
||||
---
|
||||
|
||||
small utility for creating DOM trees from javascript arrays.
|
||||
|
||||
note that this doesn't actually take a json string, but rather an actual array, as input. `array_as_html` would be a bit inaccurate though, since it also handles some other things such as functions and strings in ways that make sense.
|
||||
|
@ -6,35 +16,6 @@ to use, clone/submodule/subtree/whatever the `main` branch, and import `json_as_
|
|||
|
||||
to see a demo, or contribute, clone the `dev` branch.
|
||||
|
||||
# example
|
||||
|
||||
here's the demo array being used at the time of writing this:
|
||||
|
||||
```javascript
|
||||
[
|
||||
"div",
|
||||
[
|
||||
["id", "wrapper"],
|
||||
["class", "demo_div"],
|
||||
],
|
||||
[
|
||||
["h1", [], "header :)"],
|
||||
["p", [], "paragraph! meow"],
|
||||
["p", [], "another paragraph!! this is so cool"],
|
||||
state => ["button", [
|
||||
["onclick", _ => {
|
||||
state.set("clicked", true);
|
||||
render();
|
||||
}]
|
||||
], "it can even do buttons!"],
|
||||
state => ["p", [], state.get("clicked") ? "clicked" : "not clicked"],
|
||||
],
|
||||
]
|
||||
|
||||
```
|
||||
|
||||
it assumes a function `render` which replaces the contents of the `<body>` with the result of calling `json_as_html` with this array as argument. it also assumes a `Map` called `state`.
|
||||
|
||||
# how to use
|
||||
|
||||
the `json_as_html` function takes two arguments:
|
||||
|
|
20
src/core.mjs
20
src/core.mjs
|
@ -12,7 +12,7 @@ export function json_as_html (json, state = new Map()) {
|
|||
}
|
||||
|
||||
if (typeof json === "function") {
|
||||
return json_as_html(json(state), state);
|
||||
return from_function(json, state);
|
||||
}
|
||||
|
||||
const [type, attributes = [], children = []] = json;
|
||||
|
@ -32,3 +32,21 @@ export function json_as_html (json, state = new Map()) {
|
|||
|
||||
return elem;
|
||||
}
|
||||
|
||||
// these two functions are pretty messy.
|
||||
function from_function (fn, state) {
|
||||
const [after, has_run_after] = delayed(fn => elem => fn(elem));
|
||||
const initial = json_as_html(fn(state, after), state);
|
||||
if (has_run_after()) after(initial);
|
||||
return initial;
|
||||
}
|
||||
function delayed (fn) {
|
||||
let has_run_once = false;
|
||||
let initial_result = undefined;
|
||||
return [(...args) => {
|
||||
if (has_run_once) return initial_result(...args);
|
||||
has_run_once = true;
|
||||
initial_result = fn(...args);
|
||||
return initial_result;
|
||||
}, _ => has_run_once];
|
||||
}
|
||||
|
|
32
src/demo.mjs
32
src/demo.mjs
|
@ -15,18 +15,42 @@ const demo = [
|
|||
state => ["button", [
|
||||
["onclick", _ => {
|
||||
state.set("clicked", true);
|
||||
render();
|
||||
trigger_event("button_pressed");
|
||||
}]
|
||||
], "it can even do buttons!"],
|
||||
state => ["p", [], state.get("clicked") ? "clicked" : "not clicked"],
|
||||
(state, after) => {
|
||||
// this is very messy.
|
||||
const generate = _ => ["p", [], state.get("clicked") ? "clicked" : "not clicked"];
|
||||
after(elem => listen_event("button_pressed", _ => elem.replaceWith(json_as_html(generate(), state))));
|
||||
|
||||
return generate();
|
||||
},
|
||||
["ul",
|
||||
[],
|
||||
[
|
||||
["li", [], "meow"],
|
||||
["li", [], "uwu"],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
const state = new Map();
|
||||
let event_listeners = new Map();
|
||||
|
||||
function trigger_event (name) {
|
||||
if (event_listeners.has(name)) {
|
||||
event_listeners.get(name).forEach(fn => fn());
|
||||
}
|
||||
}
|
||||
|
||||
function listen_event (name, fn) {
|
||||
if (!event_listeners.has(name)) event_listeners.set(name, []);
|
||||
event_listeners.get(name).push(fn);
|
||||
}
|
||||
|
||||
function render () {
|
||||
document.body.innerHTML = "";
|
||||
document.body.appendChild(json_as_html(demo, state));
|
||||
document.body.appendChild(json_as_html(demo));
|
||||
}
|
||||
|
||||
render();
|
||||
|
|
Loading…
Reference in a new issue