Vue.js源码解析
Aug 17, 2016
以下内容还在研究中,描述可能不完全准确,仅供参考
为每一处需要动态更新的DOM节点,创建一个属性对象
1
2
3
4
5
6var attrs = map.call(node.attributes, function (attr) {
return {
name: attr.name,
expressions: attr.value.split(',')
}
})根据attr对象,分析绑定关系
1
2
3
4
5attrs.forEach(function (attr) {
attr.expressions.forEach(function (exp) {
var binding = bindingParser.parse(attr.name, exp)
})
})解析属性对象,从指令函数库中,取出对应指令函数
指令函数存在,创建binding对象1
2
3
4
5
6
7parse: function (dirname, expression) {
var dir = directives[dirname]
return dir && valid
? new Binding(dirname, expression)
: null
}解析指令,存储在binding对象上
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
49function Binding(directiveName, expression) {
var directive = directives[directiveName]
if (typeof directive === 'function') {
this._update = directive
} else {
for (var prop in directive) {
if (prop === 'update') {
this['_update'] = directive.update
} else {
this[prop] = directive[prop]
}
}
}
}
//
this.key = argMatch
? argMatch[2].trim()
: rawKey.trim()
this.arg = argMatch
? argMatch[1].trim()
: null
//
this.filters = filterExpressions.map(function (filter) {
var tokens = filter.slice(1)
.match(FILTER_TOKEN_RE)
.map(function (token) {
return token.replace(QUOTE_RE, '').trim()
})
return {
name: tokens[0],
apply: filters[tokens[0]],
args: tokens.length > 1
? tokens.slice(1)
: null
}
})
//
Seed.prototype._compileNode = function (node, root) {
var self = this
self._bind(node, binding)
}
Seed.prototype._bind = function (node, bindingInstance) {
bindingInstance.seed = this
bindingInstance.el = node
}子节点遍历解析
1
2
3
4
5if (node.childNodes.length) {
each.call(node.childNodes, function (child) {
self._compileNode(child)
})
}指令对象观测的数据变化
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
32Seed.prototype._bind = function (node, bindingInstance) {
var binding = seed._bindings[key] || seed._createBinding(key)
binding.instances.push(bindingInstance)
if (bindingInstance.bind) {
bindingInstance.bind(binding.value)
}
}
Seed.prototype._createBinding = function (key) {
var binding = {
value: null,
instances: []
}
this._bindings[key] = binding
// bind accessor triggers to scope
Object.defineProperty(this.scope, key, {
get: function () {
return binding.value
},
set: function (value) {
binding.value = value
binding.instances.forEach(function (instance) {
instance.update(value)
})
}
})
return binding
}解析完root节点,继续解析子节点
1
2
3
4
5
6
7
8Seed.prototype._compileNode = function (node, root) {
var self = this
if (node.childNodes.length) {
each.call(node.childNodes, function (child) {
self._compileNode(child)
})
}
}初始化变量,触发setters
1
2
3
4
5function Seed(el, data, options) {
for (key in dataCopy) {
this.scope[key] = dataCopy[key]
}
}