forked from RubyLouvre/avalon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path06 EventBus.js
108 lines (107 loc) · 4.03 KB
/
06 EventBus.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
105
106
107
108
/*********************************************************************
* 事件总线 *
**********************************************************************/
var EventBus = {
$watch: function(type, callback) {
if (typeof callback === "function") {
var callbacks = this.$events[type]
if (callbacks) {
callbacks.push(callback)
} else {
this.$events[type] = [callback]
}
} else { //重新开始监听此VM的第一重简单属性的变动
this.$events = this.$watch.backup
}
return this
},
$unwatch: function(type, callback) {
var n = arguments.length
if (n === 0) { //让此VM的所有$watch回调无效化
this.$watch.backup = this.$events
this.$events = {}
} else if (n === 1) {
this.$events[type] = []
} else {
var callbacks = this.$events[type] || []
var i = callbacks.length
while (~--i < 0) {
if (callbacks[i] === callback) {
return callbacks.splice(i, 1)
}
}
}
return this
},
$fire: function(type) {
var special, i, v, callback
if (/^(\w+)!(\S+)$/.test(type)) {
special = RegExp.$1
type = RegExp.$2
}
var events = this.$events
var args = aslice.call(arguments, 1)
var detail = [type].concat(args)
if (special === "all") {
for (i in avalon.vmodels) {
v = avalon.vmodels[i]
if (v !== this) {
v.$fire.apply(v, detail)
}
}
} else if (special === "up" || special === "down") {
var elements = events.expr ? findNodes(events.expr) : []
if (elements.length === 0)
return
for (i in avalon.vmodels) {
v = avalon.vmodels[i]
if (v !== this) {
if (v.$events.expr) {
var eventNodes = findNodes(v.$events.expr)
if (eventNodes.length === 0) {
continue
}
//循环两个vmodel中的节点,查找匹配(向上匹配或者向下匹配)的节点并设置标识
Array.prototype.forEach.call(eventNodes, function(node) {
Array.prototype.forEach.call(elements, function(element) {
var ok = special === "down" ? element.contains(node) : //向下捕获
node.contains(element) //向上冒泡
if (ok) {
node._avalon = v //符合条件的加一个标识
}
});
})
}
}
}
var nodes = DOC.getElementsByTagName("*") //实现节点排序
var alls = []
Array.prototype.forEach.call(nodes, function(el) {
if (el._avalon) {
alls.push(el._avalon)
el._avalon = ""
el.removeAttribute("_avalon")
}
})
if (special === "up") {
alls.reverse()
}
for (i = 0; callback = alls[i++]; ) {
if (callback.$fire.apply(callback, detail) === false) {
break
}
}
} else {
var callbacks = events[type] || []
var all = events.$all || []
for (i = 0; callback = callbacks[i++]; ) {
if (isFunction(callback))
callback.apply(this, args)
}
for (i = 0; callback = all[i++]; ) {
if (isFunction(callback))
callback.apply(this, arguments)
}
}
}
}