Pernah penasaran bagaimana React, Vue, atau Svelte bisa memperbarui tampilan dengan cepat tanpa me-render ulang seluruh halaman?
Rahasianya ada pada konsep Virtual DOM dan Reactive Rendering.
Di artikel ini, kita akan membangun mini framework JavaScript sederhana dengan konsep yang sama seperti React:
-
Menggunakan Virtual DOM untuk mendeteksi perubahan.
-
Merender ulang hanya bagian yang berubah.
-
Mengelola state dan component dengan efisien.
Framework ini ringan, hanya sekitar 50 baris kode, tapi cukup kuat untuk memahami dasar dari frontend reactivity engine.
Apa Itu Virtual DOM?
Virtual DOM adalah representasi virtual dari struktur HTML dalam bentuk JavaScript Object.
Alih-alih langsung memanipulasi DOM asli (yang lambat), kita:
-
Menyimpan versi virtual dari DOM di memori.
-
Membandingkan versi lama dan baru setiap kali ada perubahan.
-
Hanya memperbarui elemen yang berbeda di DOM nyata (real DOM diffing).
Intinya:
Virtual DOM membuat proses rendering jadi lebih efisien dan cepat, karena browser tidak perlu menggambar ulang seluruh halaman.
Membuat Virtual DOM Node
Kita mulai dengan fungsi pembuat elemen virtual:
function h(type, props = {}, ...children) {
return { type, props, children };
}
Contoh penggunaan:
const vdom = h("div", { class: "box" },
h("h2", null, "Hello World!"),
h("p", null, "Belajar membuat mini framework JS.")
);
Hasilnya adalah object JavaScript seperti ini:
{
"type": "div",
"props": { "class": "box" },
"children": [
{ "type": "h2", "props": null, "children": ["Hello World!"] },
{ "type": "p", "props": null, "children": ["Belajar membuat mini framework JS."] }
]
}
Render Virtual DOM ke Real DOM
Selanjutnya kita buat fungsi untuk mengubah Virtual DOM menjadi elemen HTML nyata.
function render(vnode) {
if (typeof vnode === "string") {
return document.createTextNode(vnode);
}
const el = document.createElement(vnode.type);
for (const [key, value] of Object.entries(vnode.props || {})) {
el.setAttribute(key, value);
}
vnode.children.forEach(child => el.appendChild(render(child)));
return el;
}
Sekarang kamu bisa melakukan:
const app = render(vdom);
document.getElementById("root").appendChild(app);
Dan hasilnya akan tampil di browser seperti HTML biasa.
Diffing Algorithm (Membandingkan Virtual DOM Lama dan Baru)
Berikut inti dari reaktivitas:
Kita akan membuat fungsi updateElement() yang hanya memperbarui bagian yang berubah antara Virtual DOM lama dan baru.
function updateElement(parent, newNode, oldNode, index = 0) {
if (!oldNode) {
parent.appendChild(render(newNode));
} else if (!newNode) {
parent.removeChild(parent.childNodes[index]);
} else if (changed(newNode, oldNode)) {
parent.replaceChild(render(newNode), parent.childNodes[index]);
} else if (newNode.type) {
const newLength = Math.max(newNode.children.length, oldNode.children.length);
for (let i = 0; i < newLength; i++) {
updateElement(parent.childNodes[index], newNode.children[i], oldNode.children[i], i);
}
}
}
function changed(node1, node2) {
return typeof node1 !== typeof node2 ||
(typeof node1 === "string" && node1 !== node2) ||
node1.type !== node2.type;
}
Dengan fungsi ini, DOM akan hanya berubah di bagian yang perlu — seperti yang dilakukan React saat re-render.
Membuat State Reaktif
Sekarang tambahkan sistem state reaktif agar setiap kali data berubah, Virtual DOM diperbarui otomatis.
function createApp(component, rootId) {
const root = document.getElementById(rootId);
let oldVNode = null;
let state = component.state;
function renderApp() {
const newVNode = component.view(state);
updateElement(root, newVNode, oldVNode);
oldVNode = newVNode;
}
component.setState = (newState) => {
state = { ...state, ...newState };
renderApp();
};
renderApp();
}
Contoh: Counter Component
Sekarang kita buat contoh nyata seperti di React:
const Counter = {
state: { count: 0 },
view: (state) =>
h("div", { class: "counter" },
h("h2", null, `Count: ${state.count}`),
h("button", { onclick: "Counter.setState({count: Counter.state.count + 1})" }, "+"),
h("button", { onclick: "Counter.setState({count: Counter.state.count - 1})" }, "-")
)
};
createApp(Counter, "root");
<div id="root"></div>
Setiap kali tombol ditekan, state berubah dan hanya bagian angka yang di-render ulang — tanpa refresh halaman.
Penjelasan Mekanisme Lengkap
-
h()membuat representasi Virtual DOM. -
render()mengubah Virtual DOM menjadi elemen nyata. -
updateElement()membandingkan DOM lama dan baru, lalu hanya memperbarui bagian yang berubah. -
createApp()mengelola state dan re-rendering otomatis.
Dengan kombinasi ini, kamu sudah memiliki mini framework JavaScript reaktif yang meniru arsitektur React versi ringan.
Pengembangan Lebih Lanjut
Beberapa fitur lanjutan yang bisa kamu tambahkan:
-
Router sederhana: Navigasi halaman tanpa reload.
-
Global store: Manajemen state bersama seperti Redux.
-
Component nested: Komponen di dalam komponen.
-
Event binding dinamis: Listener langsung dari props.
Jika dikembangkan terus, kamu akan punya framework ringan buatan sendiri yang cocok untuk belajar konsep reactivity engine.
Kesimpulan
Dengan hanya beberapa puluh baris JavaScript, kita bisa membangun:
-
Sistem Virtual DOM untuk update efisien,
-
Reactive state yang otomatis merender ulang tampilan, dan
-
Struktur component-based seperti framework modern.
Framework seperti React atau Vue sebenarnya hanyalah abstraksi dari konsep sederhana ini, hanya saja dikembangkan lebih kompleks dan optimal.
Mempelajari dasarnya memberi kamu pemahaman mendalam bagaimana frontend modern bekerja — dan memungkinkan kamu menciptakan versi unik sesuai kebutuhanmu.