D3事件监听与分发

事件监听主要是指为选择的DOM元素添加或删除指定DOM事件类型的listenerlistener函数参数包括数据d和索引i,上下文this指向当前DOM元素。

事件分发器(dispatch),也可以理解为消息分发器。主要用来解决视图间的联动,即一个事件触发多个动作。结合当前项目,和VUE的$dispatch在功能上比较类似。

D3事件监听

事件监听主要是指为选择的DOM元素添加或删除指定DOM事件类型的listenerlistener函数参数包括数据d和索引i,上下文this指向当前DOM元素。

selection.on(types[,listener[,capture]])

事件的添加

1
2
3
4
selection.on('click', function(d, i) {
<!--事件响应逻辑 -->
})

事件的删除

1
selection.on('click', null)

*注意:如果相同元素、相同类型的事件监听已经注册,新的监听加入将会删除原来额监听。

如果在监听中想获得当前事件,可以通过d3.event这个全部对象获得


D3事件分发器

事件分发器(dispatch),也可以理解为消息分发器。主要用来解决视图间的联动,即一个事件触发多个动作。结合当前项目,和VUE的$dispatch在功能上比较类似。

常用方法

  • d3.dispatch(types…)
  • dispatch.on(type[, listener])
  • dispatch.type(arguments…)

d3.dispatch(types…)

创建一个事件分发器,通过types参数指定事件的名称,用于之后的事件分发和监听。

1
var dispatch = d3.dispatch('start', 'end')

上述代码就创建了一个包含start事件和end事件的分发器。

dispatch.on(type[, listener])

为指定事件添加或删除一个事件监听。

1
2
3
dispatch.on('start', function() {
<!--事件处理-->
})

上述代码对start事件进行监听,并执行相应的逻辑处理

1
dispatch.on('start', null)

上述代码移除了start事件的监听

*注意:对同一事件重复监听,会导致已经存在的监听被删除。这时就需要引入命名空间,这也是解决多个视图对同一事件响应的方法,如”start.pie’和’start.bar’。

dispatch.type(arguments…)

通知并将参数arguments传递个注册的监听(这里的type不是方法名)。正常调用如下:

1
diapatch.start()

arguments作为参数传递给监听函数,上下文this作为监听函数的上下文。在实际应用场景中,常常需要改变this上下文,就可以如下调用:

1
2
3
4
selection.on('click', function(d, i) {
<!--改变上下文为dom对象,传递对象绑定的datum和index-->
dispatch.start.call(this, d, i)
})

source

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
d3.dispatch = function() {
var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
return dispatch;
};
function d3_dispatch() {}
d3_dispatch.prototype.on = function(type, listener) {
var i = type.indexOf("."), name = "";
if (i >= 0) {
name = type.slice(i + 1);
type = type.slice(0, i);
}
if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
if (arguments.length === 2) {
if (listener == null) for (type in this) {
if (this.hasOwnProperty(type)) this[type].on(name, null);
}
return this;
}
};
function d3_dispatch_event(dispatch) {
var listeners = [], listenerByName = new d3_Map();
function event() {
var z = listeners, i = -1, n = z.length, l;
while (++i < n) if (l = z[i].on) l.apply(this, arguments);
return dispatch;
}
event.on = function(name, listener) {
var l = listenerByName.get(name), i;
if (arguments.length < 2) return l && l.on;
if (l) {
l.on = null;
listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
listenerByName.remove(name);
}
if (listener) listeners.push(listenerByName.set(name, {
on: listener
}));
return dispatch;
};
return event;
}