d3将事件的名称划分为两部分,第一部分为事件的类型,如click、input、focus等,也可以是自定义的事件类型,第二部分为事件的生命周期(如start、end等),也可以是命名空间、个人标示符等自定义的字符串,这两部分合起来就成为了一个唯一的事件标示符。一个唯一的事件标识符只能注册一个唯一的事件处理函数,如果注册多个,后面注册的事件处理函数会覆盖之前的事件处理函数。
我们可以直接在d3选择的集合上注册事件,所以既可以进行链式写法,还可以批量注册事件,如下:
d3.selectAll('button')
// 绑定数据,必须是数组
.data([{
username : 'yiifaa',
sex : 1
}, {
username : 'yiifee',
sex : 0
}])
// 获取到更新的集
.enter()
.append('button')
.text(function(d) {
return d.username;
})
// 事件注册函数的参数为绑定的数据
.on('click', function(d) {
var sexCn = '男';
if(d.sex === 0) {
sexCn = '女';
}
// 进行名称的处理
alert('Hello,' + d.username);
// 进行性别的处理
alert(d.username + '的性别是' + sexCn);
});
在上面的代码里,按钮绑定的click事件同时处理了两件不太相关的事件,不利于代码的维护,也不利于代码的扩展,这时就可以充分利用d3事件名称的特性,为按钮点击事件注册多个事件名称与相应的事件处理函数,如下:
// 把上面的事件注册代码换为下面的代码
// 如果继续保留上面的事件注册代码,则会触发3次点击事件(因为事件名称的唯一性)
d3.selectAll('button')
// 事件注册函数的参数为绑定的数据
.on('click.hello', function(d) {
// 进行名称的处理
alert('Hello,' + d.username);
})
.on('click.sex', function(d) {
var sexCn = '男';
if(d.sex === 0) {
sexCn = '女';
}
// 进行性别的处理
alert(d.username + '的性别是' + sexCn);
});
现在代码很好地实现了业务逻辑的分离,提高了健壮性,更重要的是,事件更容易卸载了。在d3里,卸载事件非常容易,只需要将事件名称对应的事件处理函数重新注册为null即可,如下:
// 取消对hello事件的注册
d3.selectAll('button')
// 卸载click.hello处理事件函数
.on('click.hello', null);
// 现在将不会输出类似于"hello, yiifaa"的信息了