这是d3设置的一种调度机制,类似于node里的eventEmitter。
例如,要为开始和结束时间创建调度。
var dispatch = d3.dispatch("start", "end");
然后用on来注册回调函数。
dispatch.on("start", callback1);
dispatch.on("start.foo", callback2);
dispatch.on("end", callback3);
然后可以使用dispatch.call和dispatch.apply启用回调:
dispatch.call("start");
就像function.call你可以指定上下文,和任意参数‘
dispatch.call("start", {about: "I am a context object"}, "I am an argument");
d3.dispatch(types…)
为指定的事件类型创建新的调度,时间类型都是字符串,例如start,end
dispatch.on(typenames[, callback])
为时间指定callback,如果该事件已经指定了callback,则替换掉。
dispatch.copy()
返回dispatch对象的值拷贝
dispatch.call(type[, that[, arguments…]])
激活指定类型的回调函数,并可以指定context
dispatch.apply(type[, that[, arguments]])
和call类似,举个例子,如果想在click后调用custom 的回调函数
selection.on("click", function() {
dispatch.apply("custom", this, arguments);
});
dispatch的源码算是比较简单吧,默认返回的是一个封装好的dispatch对象,通过调用会产生一个Dispatch,该对象对用的方法就是上述提到的方法,此外两个函数get和set,一个是获取给定类型的callback函数,以一个设置callback,Dispatch中用一个对象存储类型和callback函数。
var noop = {value: function() {}};
function dispatch() {
for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t);
_[t] = [];
}
return new Dispatch(_);
}
function Dispatch(_) {
this._ = _;
}
function parseTypenames(typenames, types) {
return typenames.trim().split(/^|\s+/).map(function(t) {
var name = "", i = t.indexOf(".");
if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
return {type: t, name: name};
});
}
Dispatch.prototype = dispatch.prototype = {
constructor: Dispatch,
on: function(typename, callback) {
var _ = this._,
T = parseTypenames(typename + "", _),
t,
i = -1,
n = T.length;
// If no callback was specified, return the callback of the given type and name.
if (arguments.length < 2) {
while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
return;
}
// If a type was specified, set the callback for the given type and name.
// Otherwise, if a null callback was specified, remove callbacks of the given name.
if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
while (++i < n) {
if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);
else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);
}
return this;
},
copy: function() {
var copy = {}, _ = this._;
for (var t in _) copy[t] = _[t].slice();
return new Dispatch(copy);
},
call: function(type, that) {
if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
},
apply: function(type, that, args) {
if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
}
};
function get(type, name) {
for (var i = 0, n = type.length, c; i < n; ++i) {
if ((c = type[i]).name === name) {
return c.value;
}
}
}
function set(type, name, callback) {
for (var i = 0, n = type.length; i < n; ++i) {
if (type[i].name === name) {
type[i] = noop, type = type.slice(0, i).concat(type.slice(i + 1));
break;
}
}
if (callback != null) type.push({name: name, value: callback});
return type;
}
export default dispatch;