-
Notifications
You must be signed in to change notification settings - Fork 5
/
vue-vdom.js
63 lines (57 loc) · 1.7 KB
/
vue-vdom.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Create a virtual node
export function h(tag, props, children) {
return { tag, props, children };
}
// tag: h1
// props: { class: 'text-red-500'}
// children: 'Hello'
// Add a virtual node onto the DOM
export function mount(vnode, container) {
const el = document.createElement(vnode.tag);
vnode.el = el;
// Handle props
for (const key in vnode.props) {
// key: class
// vnode.props[key]: 'text-red-500
if (key.startsWith('on')) {
// When it's an event
// onClick => click
const eventName = key.slice(2).toLowerCase();
el.addEventListener(eventName, vnode.props[key]);
} else {
// When it's a regular attribute
el.setAttribute(key, vnode.props[key]);
}
}
// Add children
if (typeof vnode.children === 'string') {
// Text
el.textContent = vnode.children;
} else if (Array.isArray(vnode.children)) {
// Array of vnodes
vnode.children.forEach(child => mount(child, el));
} else {
// Single vnode
mount(vnode.children, el);
}
// Add to real DOM
container.appendChild(el);
}
// Remove a vnode from the real DOM
export function unmount(vnode) {
vnode.el.parentNode.removeChild(vnode.el);
}
// Check for differences and apply changes
// (very simplified version)
export function patch(vnode1, vnode2) {
const el = vnode1.el;
vnode2.el = el;
if (typeof vnode2.children === 'string') {
el.textContent = vnode2.children;
} else {
// Assume an array of h()
for (let i = 0; i < vnode2.children.length; i++) {
patch(vnode1.children[i], vnode2.children[i]);
}
}
}