How Updates Work
What happens between changing a property and seeing the DOM update, in four steps.
The Update Pipeline
Every DOM update in WildflowerJS follows the same four-step pipeline:
this.count++↓
2. Dependency Lookup
Which bindings read
count?↓
3. Effects Scheduled
Changes coalesce into one consistent update
↓
4. Targeted DOM Updates
Only affected nodes are touched
This pipeline runs automatically. You never interact with it directly. Just change state and the framework handles the rest.
Step by Step
1. State Change: Proxy Interception
WildflowerJS wraps component state in a JavaScript Proxy. When you assign a property, the Proxy's set trap fires:
// You write:
this.count++
// The Proxy intercepts this as:
// set(target, 'count', 1)
// → records that 'count' changed
// → schedules an update
This works for any mutation: direct assignment, nested property changes, array methods:
this.count++ // direct assignment
this.user.name = "Jane" // nested property
this.items.push({ text: "New" }) // array mutation
this.items.splice(2, 1) // array splice
All of these are intercepted automatically. No special syntax, no wrapper functions, no immutable update patterns required.
2. Dependency Lookup: Path-Level Tracking
When the framework processes a binding like data-bind="count", it records that this specific DOM node depends on the count property. This creates a mapping:
Property Path → DOM Nodes
───────────── ─────────
count → span#counter-display
user.name → h1#greeting, span#profile-name
items → ul#todo-list (list binding)
items[].text → each li text node
When count changes, the framework looks up exactly which nodes depend on it. No tree walking, no component re-rendering, no diffing. Just a direct lookup.
Computed properties live in the same graph. State, computeds, effects, and bindings are all nodes in one dependency graph, so a binding that reads a computed depends, through it, on the state the computed reads; a change wakes the chain and nothing else.
3. Effects Scheduled: Automatic Batching
Changes made in the same synchronous block coalesce. Some updates apply at the moment of the write and others are queued and flushed together on a microtask; which is which is an internal optimization detail that may change between releases. The guarantee to build on is simple: by the time your await, timeout, or next event handler runs, the DOM reflects your state, and within any frame the user sees a consistent picture.
// All three changes happen synchronously
this.firstName = "Jane"
this.lastName = "Smith"
this.email = "jane@example.com"
// The DOM settles with the final values.
// No half-applied state ever reaches the screen.
This is automatic. You never need to wrap changes in a batch function or call a flush method, and you should not build on intra-tick DOM timing; coalescing happens on its own.
4. Targeted DOM Updates: Surgical Precision
When the microtask fires, only the specific DOM nodes that depend on changed properties are updated:
<div data-component="profile">
<h1 data-bind="name"></h1> <!-- Updated ✓ -->
<p data-bind="bio"></p> <!-- NOT touched -->
<span data-bind="email"></span> <!-- NOT touched -->
</div>
If only name changed, only the <h1> is touched. The <p> and <span> are untouched. The framework doesn't even look at them.
How This Differs from Virtual DOM
Virtual DOM (React, Vue)
- State changes
- Re-render entire component to virtual tree
- Diff old virtual tree vs new virtual tree
- Compute minimal set of DOM patches
- Apply patches to real DOM
Work is proportional to component size
WildflowerJS
- State changes
- Look up which bindings depend on changed path
- Update those DOM nodes directly
Work is proportional to number of changes
The key difference: virtual DOM frameworks do work proportional to component size (they must re-render and diff the entire component). WildflowerJS does work proportional to what actually changed: if one property changed and two DOM nodes depend on it, only those two nodes are touched regardless of how large the component is.
List Updates: Operation Detection
Lists get special treatment. Instead of re-rendering the entire list when an array changes, WildflowerJS detects what kind of operation occurred and applies the minimal DOM change:
| Array Operation | DOM Response |
|---|---|
items.push(item) |
Append one new node |
items.pop() |
Remove last node |
items.splice(2, 1) |
Remove node at index 2 |
items.unshift(item) |
Prepend one new node |
items[i] = newItem |
Update node at index i in place |
items = [...items].sort(fn) |
Reconcile with minimal moves |
Nested Reactivity
The Proxy wrapping is deep: it covers nested objects and arrays automatically:
// All of these trigger updates automatically:
this.user.address.city = "Portland" // deep nested property
this.columns[2].cards.push(newCard) // nested array mutation
this.settings = { ...this.settings, theme: "dark" } // object replacement
There is no depth limit. The framework tracks changes at whatever level they occur and updates only the bindings that depend on the changed path.