-
Notifications
You must be signed in to change notification settings - Fork 1
/
Compile.js
103 lines (97 loc) · 2.52 KB
/
Compile.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
93
94
95
96
97
98
99
100
101
102
103
let Watcher = require('./Watcher')
let toArray = require('./Utils').toArray
let directives = require('./directives')
function Compile(el, vm) {
this.el = el
this.vm = vm
this.analyElement(el)
}
// 开始分析节点
Compile.prototype.analyElement = function(node) {
switch(node.nodeType) {
// node
case 1:
this.splitElement(node)
break
// text
case 3:
this.replaceElement(node)
break
default:
return
}
}
// 找出子节点
Compile.prototype.splitElement = function(node) {
if (node.tagName === 'INPUT' && node.hasAttribute('v-model')) {
let exp = node.getAttribute('v-model').trim()
let descriptor = {
name: 'model',
exp: exp,
def: directives.model
}
this.vm._directives.push(new Watcher(descriptor, this.vm, node))
return
}
if(node.hasChildNodes()) {
Array.from(node.childNodes).forEach(this.analyElement, this)
}
}
// 用 DocumentFragment 替换 TextNode
Compile.prototype.replaceElement = function (node) {
let self = this
let text = node.nodeValue
let regTag = /{{(.*?)}}/g
if(!regTag.test(text)) return
let tokens = this.getTokens(regTag, text)
let frag = document.createDocumentFragment()
tokens.forEach(function(token) {
let el = token.tag ? self.processTextToken(token) : document.createTextNode(token.value)
frag.appendChild(el)
})
let fragClone = frag.cloneNode(true)
let childNodes = toArray(fragClone.childNodes)
tokens.forEach(function (token, i) {
let value = token.value
if (token.tag) {
let cnode = childNodes[i]
self.vm._directives.push(new Watcher(token.descriptor, self.vm, cnode))
}
})
node.parentNode.replaceChild(fragClone, node)
}
Compile.prototype.getTokens = function getTokens(regTag, text) {
let lastIndex = regTag.lastIndex = 0
let index, value, matchs, tokens = []
while(matchs = regTag.exec(text)) {
index = matchs.index
if(index > lastIndex) {
tokens.push({
value: text.slice(lastIndex, index)
})
}
value = matchs[1]
tokens.push({
tag: true,
value: value.trim()
})
lastIndex = index + matchs[0].length
}
if(lastIndex < text.length) {
tokens.push({
value: text.slice(lastIndex)
})
}
return tokens
}
Compile.prototype.processTextToken = function processTextToken(token) {
let el = document.createTextNode(' ')
// 简化,双向绑定,text 模式
token.descriptor = {
name: 'text',
exp: token.value,
def: directives.text
}
return el
}
module.exports = Compile