因为习惯了jquery的attr(obj)批量添加属性,所以刚开始看到d3为dom添加属性要一个一个添加的时候真的是十分想吐槽,既然想实现attr(obj),根据传入对象的键值对批量添加dom属性,那就得改它的源码了。
因为看d3的dom是这样选择的:
d3.selectAll("h1");
那么直接打印这个,控制台显示的是一个Selection对象,如图:
并且获得这个节点之后,是可以直接通过attr()来为dom添加属性的,那么我们就来看d3下的selection,控制台console.log(d3):
果不其然,d3下有个selection对象,selection对象下有attr()这个原型方法;
此时,我就想了干脆直接重写d3.selection.prototype.attr()这个方法,于是一顿操作猛如虎,写下了如下代码:
然后:
一看页面,没反应(其实这里由于d3的dom处理规则问题导致我这句代码是有问题的,稍后会讲解)
那怎么办呢,直接看他attr的源码吧:
打开之后:
我们看他这个对外暴露的方法:
首先他通过this.node()获取dom对象,所以之前我重写的方法里面的this拿到的是d3获取的selection对象,需要将其转为DOM对象;
然后d3的这个方法里面,判断参数个数小于2的时候(那就是1咯),执行getter方法获取属性值,这个没有异议;
针对setter,为了支持对象型参数,并实现批量添加属性
于是,添加了如下代码:
然后,验证一下(为h1添加两个属性):
结果只有第一个获得了两个属性,一方面验证我之前添加的代码是没有问题的,一方面验证selectAll()并不能不会循环执行后续操作,但想到之前绑定数据之后的text()是可以实现循环赋值的,那么:
至此,便可以愉快地批量添加属性了。不用像网上教程那样,千篇一律的多重attr()操作:
但是!重点来了,以上简单的修改,不难发现只支持字符串型属性值,d3可是支持函数型属性值得啊,不用怕,后续我也针对函数型属性值作了补充:
页面使用:
页面展示:
至此,这个函数应该算是比较完善了,反正我用得挺顺手
注:
我们现在的HTML都是通过DOCTYPE来声明,XHTML中有xmlns声明,svg标签也是有的,d3中有删除通过命名空间和名称指定的属性的方法,但是我们现在写的时候,都不需要添加命名空间,所以我修改的方法就没有添加removeAttributeNS()支持了,最终版: