Documentation v2.0.3

Core Concepts

How an RJS instance (src/model/RJS.ts) is created and re-rendered, and why each render is a single, non-reactive pass.

Instance Lifecycle

"#selector".RJS(body) looks up the target element via body.id, clones it as the pristine template (#model), and stores data/event/when on the instance. If the selector resolves to null, the constructor returns early and no instance is initialized.

graph TB
    Entry["#selector.RJS(body)"] --> Ctor["constructor: locate node, cloneNode(true)"]
    Ctor --> Init["#init()"]
    Init --> Before["when.before_render()"]
    Before -->|"returns false"| Cancel["render cancelled"]
    Before -->|"continue"| SetDOM["#SET_DOM(body, data) — recursive walk"]
    SetDOM --> After["when.rendered()"]

app.renew(body) restores the DOM from the cloned #model (replaceChildren(...this.#model.children)), merges any provided data/event/when keys into the existing instance state (unmentioned keys keep their prior value), and re-runs #init(). This is the only way an RJS instance re-renders — there is no automatic reactivity or dirty-checking.

before_render returning false cancels the pass, so rendered never runs and the template text stays as written:

<div id="app"><p>{{ msg }}</p></div>
<script>
    "#app".RJS({
        data: { msg: "rendered" },
        when: {
            before_render: () => {
                console.log("before_render");
                return false;
            },
            rendered: () => console.log("rendered")
        }
    });
    console.log("#app".$.textContent);
</script>
Live preview · @pardnchiu/renderjs@2.0.3

Non-Reactivity Is Deliberate

Every commented-out block in RJS.ts (#dataListener, the Object.defineProperty getter/setter pairs) is a removed reactive-observer mechanism. The shipped design renders once per #init() call and requires an explicit renew() to update — this trade-off is what the README describes as removing "the overhead of automatic reactive watching."

中文