Virtual DOM
The Virtual DOM is a core concept in Fluxus that enables efficient UI updates.
What is the Virtual DOM?
The Virtual DOM is a lightweight in-memory representation of the actual DOM. In Fluxus, it’s implemented as a tree of FluxusNode
objects that describe what the UI should look like.
Unlike the real DOM, which is expensive to manipulate, the Virtual DOM can be created and modified quickly in memory. This allows Fluxus to:
- Calculate the minimal set of changes needed to update the real DOM
- Batch multiple updates together for better performance
- Provide a more declarative API for building UIs
How It Works
The Virtual DOM system in Fluxus follows this process:
- Render: Component functions are called to produce a tree of
FluxusNode
objects - Diff: The new tree is compared with the previous one to determine what changed
- Patch: The necessary changes are applied to the real DOM
FluxusNode Hierarchy
In Fluxus, the Virtual DOM is represented by the sealed trait FluxusNode
. The main node types are:
ElementNode
Represents an HTML or SVG element:
case class ElementNode(
tag: String,
attrs: Map[String, Any],
events: Map[String, js.Function1[dom.Event, Unit]],
children: Vector[FluxusNode],
parent: Option[FluxusNode],
domNode: Option[Node],
namespace: Option[String] = None,
ref: Option[RefHook] = None,
key: Option[String] = None
) extends FluxusNode
TextNode
Represents a text node in the DOM:
case class TextNode(
text: String,
parent: Option[FluxusNode],
domNode: Option[Node]
) extends FluxusNode
ComponentNode
Represents a user-defined component:
case class ComponentNode(
component: Product => FluxusNode,
props: Product,
parent: Option[FluxusNode] = None,
domNode: Option[Node] = None,
key: Option[String] = None,
instance: Option[ComponentInstance] = None,
componentHash: Int = 0
) extends FluxusNode
RawNode
Represents a direct reference to an existing DOM element:
case class RawNode(
element: dom.Element,
parent: Option[FluxusNode] = None,
domNode: Option[Node] = None,
key: Option[String] = None
) extends FluxusNode
EmptyNode
Represents the absence of a node (like null
in React):
case object EmptyNode extends FluxusNode
Creating Virtual DOM Nodes
Fluxus provides a set of helper functions to create Virtual DOM nodes:
// Creating element nodes
div(cls := "container", "Hello, world!")
// Creating nested structures
div(
cls := "card",
h1(cls := "title", "Card Title"),
p(cls := "content", "Card content goes here")
)
// Conditional rendering
div(
if (isLoggedIn)
button(onClick := logout, "Log out")
else
button(onClick := login, "Log in")
)
Keys
When rendering lists of elements, it’s often important to provide a unique key
for each item:
ul(
items.map(item =>
li(key := item.id, item.name)
)
)
Keys help the reconciliation algorithm identify which items have changed, moved, or been removed, leading to more efficient updates.
Benefits of Virtual DOM
The Virtual DOM approach provides several benefits:
- Performance: By minimizing actual DOM operations, UI updates are faster
- Simplicity: Developers can describe UIs declaratively without worrying about DOM manipulation
- Predictability: UI rendering is a pure function of state, making behavior more predictable
- Testability: Virtual DOM trees can be tested without a browser environment