-
Notifications
You must be signed in to change notification settings - Fork 1
/
xue.js
92 lines (74 loc) · 1.97 KB
/
xue.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
87
88
89
90
91
92
; (function (root, factory) {
root.Xue = factory()
})(this /* window */, function () {
window.fakeVirtualDOM = {}
const isText = node => (
node.nodeName === '#text' &&
!!node.textContent.trim()
)
const isObject = node => (
typeof node === 'object' &&
node !== null
)
function Xue(conf) {
this.$el = document.querySelector(conf.el)
for (const key in conf.data)
this[key] = conf.data[key]
this.walkInDom(this.$el)
for (const key in conf.data)
this.reactiveBinder(this, key)
}
Xue.prototype.dispatchReactiveChange = function (key) {
const { node, text } = fakeVirtualDOM[key]
node.textContent = this.getFinalText(text)
}
Xue.prototype.reactiveBinder = function (parent, child) {
let nodeValue = parent[child]
if (isObject(parent) && isObject(nodeValue)) {
for (const key in nodeValue) {
this.reactiveBinder(nodeValue, key)
}
} else {
Object.defineProperty(parent, child, {
enumerable: true,
configurable: true,
get() {
return nodeValue
},
set: (newValue) => {
nodeValue = newValue
this.dispatchReactiveChange(child)
}
})
}
}
Xue.prototype.walkInDom = function (node) {
if (isText(node)) {
node.textContent = this.getFinalText(node)
} else {
node.childNodes.forEach(elm => {
this.walkInDom(elm)
})
}
}
Xue.prototype.getFinalText = function (textNode) {
return (textNode.textContent || textNode)
.replace(/{{ *([a-z|A-Z|\.]+) *}}/g, (match, extract) => {
extract = extract.split('.')
let value = this
let lastKey
extract.forEach(key => {
value = value[key]
lastKey = key
})
if (textNode.textContent) {
fakeVirtualDOM[lastKey] = {
node: textNode,
text: textNode.textContent,
}
}
return value
})
}
return Xue
})