-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDOM.js
executable file
·87 lines (73 loc) · 2.45 KB
/
DOM.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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
const DOM = (function() {
let rootNode
function createNode(el) {
let node = document.createElement(el.tag || 'span')
if (typeof el === 'string') {
// this is just pure text
node.innerHTML = el
return node
}
modifyNode(node, el) // properties setzen
return node
}
function modifyNode(node, newProps) {
for (prop in newProps) {
if (prop === 'tag') continue
if (prop === 'children') {
// if there was only plain text set in old node, delete it
if (node.children.length === 0 && node.innerHTML) node.innerHTML = ''
continue
}
if (node[prop] !== newProps[prop]) {
// attribut hat sich geändert
node[prop] = newProps[prop]
}
}
}
function registerRootNode(rtn) {
rootNode = rtn
}
function diffElements(parentDOMNode, childDOMNode, next) {
if (!next) return
if (typeof childDOMNode === 'undefined') {
// das Element childDOMNode existiert noch nicht -> erzeugen
childDOMNode = createNode(next)
parentDOMNode.appendChild(childDOMNode)
}
// childDOMNode existiert!
else if (childDOMNode.tagName.toLowerCase() !== next.tag
&& childDOMNode.tagName.toLowerCase() !== 'span' && next.tag !== undefined) // Ausnahme sind reine Textknoten
{
// entweder dieses Element soll gelöscht werden, oder es soll ein oder mehrere neue Elemente
// an dieser Stelle eingefügt werden. Diese Fallunterscheidung wäre sehr aufwändig, daher:
// einfach alten Knoten mit einem neuen überschreiben
let newNode = createNode(next)
childDOMNode.replaceWith(newNode)
childDOMNode = newNode // we have to set our local reference to the new node as well
}
else {
// gleiche Art von Knoten -> alles ändern, was sich geändert hat (das kann auch nichts sein!)
modifyNode(childDOMNode, next)
}
if (next.children) {
// next hat Kinder -> auch für die gucken, ob sich was geändert hat
diffElementLists(childDOMNode, next.children)
}
}
function diffElementLists(parentDOMNode, nextList) {
let children = parentDOMNode.children // Referenz auf die Kinder von parentDOMNode
while (children.length > nextList.length) {
// Lösche überzählige DOM-Knoten
parentDOMNode.lastChild.remove()
}
// Vergleiche jedes Element aus nextList mit jedem Kind-Knoten von parentDOMNode
nextList.forEach((x, i) => diffElements(parentDOMNode, children[i], nextList[i]))
}
function render(elementList) {
diffElementLists(rootNode, elementList)
}
return {
render,
registerRootNode
}
})()