-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompile.js
105 lines (88 loc) · 2.39 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
104
/*
* @Author: WangYu
* @Date: 2020-02-26 18:30:45
* @LastEditors: WangYu
* @LastEditTime: 2020-03-08 21:34:13
*/
// 遍历dom结构 解析 指令和插值表达式
class Compile{
// el是 等待编译的模板 vm是Wvue实例
constructor(el, vm) {
this.$vm = vm
this.$el = document.querySelector(el)
// 把模板中的内容移到片段中 操作
this.$fragment = this.node2Fragment(this.$el)
// 执行编译
this.compile(this.$fragment)
// 放回$el中
this.$el.appendChild(this.$fragment)
}
node2Fragment(el){
//创建片段
const fragment = document.createDocumentFragment();
let child;
while(child = el.firstChild) {
fragment.appendChild(child)
}
return fragment;
}
compile(el) {
const childNodes = el.childNodes
Array.from(childNodes).forEach(node => {
if(node.nodeType == 1) {
//console.log("编译元素" + node.nodeName)
this.compileElement(node)
} else if(this.isInter(node)) {
// 只关心{{xxx}}
// console.log('编译插值文本'+ node.textContent)
this.compileText(node)
} else {
}
// 递归子节点
if (node.children && node.childNodes.length > 0) {
this.compile(node)
}
})
}
isInter(node) {
return node.nodeType == 3 && /\{\{(.*)\}\}/.test(node.textContent)
}
// 文本替换
compileText(node) {
//RegExp.$1上一次正则表达式为true的时候 的值
console.log(RegExp.$1)
// 表达式
const exp = RegExp.$1
this.update(node, exp, 'text') // v-text
// node.textContent = this.$vm[RegExp.$1]
}
update(node, exp, dir) {
const updator = this[dir + "Updator"]
updator && updator(node, this.$vm[exp]) // 初始化更新
new Watcher(this.$vm, exp, function(value) {
updator && updator(node, value)
})
}
textUpdator(node, value) {
node.textContent = value
}
compileElement(node) {
// 关心属性
const nodeAttrs = node.attributes
Array.from(nodeAttrs).forEach(attr => {
// 规定 k-xxx="yyy"
const attrName = attr.name //k-xxx
const exp = attr.value // yyy
if(attrName.indexOf("k-")==0) {
//指令
const dir = attrName.substring(2) // xxx
// 执行
this[dir] && this[dir](node, exp)
}
})
}
text(node, exp){
this.update(node, exp , "text")
}
//等待解析 @click v-module
}