How Reactivity Works
WakaPAC's reactivity system automatically synchronizes your data with the DOM. Change a property, and the UI updates - no manual DOM manipulation required.
The Basics
When you create a WakaPAC component, all properties in your abstraction object become reactive:
wakaPAC('#app', {
count: 0,
increment() {
this.count++; // Change is detected, DOM updates scheduled
}
});
WakaPAC's reactivity engine:
- Creates proxies for all properties in your abstraction object
- Tracks dependencies - which DOM elements reference which properties
- Queues updates when properties change, avoiding redundant operations
- Batches DOM changes in microtasks for optimal performance
- Updates selectively - only affected DOM elements are modified
The Reactivity Pipeline
Deep Reactivity
Nested Objects
WakaPAC recursively wraps nested objects in proxies, making changes at any depth reactive:
<div id="app">
<p>{{user.name}}</p>
<p>Theme: {{user.preferences.theme}}</p>
<button data-pac-bind="click: changeTheme">Toggle Theme</button>
</div>
<script>
wakaPAC('#app', {
user: {
name: 'John',
preferences: {
theme: 'dark'
}
},
changeTheme() {
// Deep property changes trigger reactivity
this.user.preferences.theme =
this.user.preferences.theme === 'dark' ? 'light' : 'dark';
}
});
</script>
Array Mutations
WakaPAC intercepts array mutator methods (push, pop, splice, shift, unshift, sort, reverse) to trigger updates automatically:
<div id="app">
<ul data-pac-bind="foreach: todos" data-pac-item="todo">
<li>{{todo.text}} (Item {{$index}})</li>
</ul>
<button data-pac-bind="click: addTodo">Add Todo</button>
</div>
<script>
wakaPAC('#app', {
todos: [
{ text: 'Learn WakaPAC', completed: false },
{ text: 'Build an app', completed: false }
],
addTodo() {
// Array mutations automatically trigger re-render of the list
this.todos.push({
text: 'New todo',
completed: false
});
}
});
</script>
Objects Within Arrays
Objects stored in arrays are also wrapped in proxies, making their property changes reactive:
<div id="app">
<div data-pac-bind="foreach: todos" data-pac-item="todo" >
<input type="checkbox" data-pac-bind="checked: todo.completed">
<span>{{todo.text}} (Item {{$index}})</span>
<button data-pac-bind="click: toggleTodo">Toggle</button>
</div>
</div>
<script>
wakaPAC('#app', {
todos: [
{ text: 'Task 1', completed: false },
{ text: 'Task 2', completed: false }
],
toggleTodo(todo, index) {
// Modifying object properties inside arrays triggers reactivity
todo.completed = !todo.completed;
}
});
</script>
Foreach Index Variable
Within a foreach loop, WakaPAC provides the special variable $index containing the current iteration index (0-based). The $ prefix distinguishes it from user-defined properties, preventing naming conflicts.
You can customize the index variable name using the data-pac-index attribute:
<div data-pac-bind="foreach: items" data-pac-index="i">
<span>Item {{i}}: {{item}}</span>
</div>
Reactivity Caveats
Array Index Assignment
Direct array index assignment is reactive, but sparse array assignments may not behave as expected:
// ✅ Reactive
this.todos[0] = newTodo;
// ⚠️ Creates sparse array, may not update correctly
this.todos[100] = newTodo;
Use push(), splice(), or reassign the array for complex operations.
Primitive Value Reassignment
When passing primitive values to child components or functions, changes to the original won't affect the copy:
let count = this.count; // count is now a copy
count++; // this.count is unchanged
Always modify properties directly on this to maintain reactivity.