总要有人来改变世界的,为什么不能是你呢

d3.js(v5.7)的attr()函数完善(添加obj支持)

因为习惯了jquery的attr(obj)批量添加属性,所以刚开始看到d3为dom添加属性要一个一个添加的时候真的是十分想吐槽,既然想实现attr(obj),根据传入对象的键值对批量添加dom属性,那就得改它的源码了。

因为看d3的dom是这样选择的:

d3.selectAll("h1");

那么直接打印这个,控制台显示的是一个Selection对象,如图:

image.png

并且获得这个节点之后,是可以直接通过attr()来为dom添加属性的,那么我们就来看d3下的selection,控制台console.log(d3):

image.png

果不其然,d3下有个selection对象,selection对象下有attr()这个原型方法;

此时,我就想了干脆直接重写d3.selection.prototype.attr()这个方法,于是一顿操作猛如虎,写下了如下代码:

image.png

然后:

image.png

一看页面,没反应(其实这里由于d3的dom处理规则问题导致我这句代码是有问题的,稍后会讲解)

那怎么办呢,直接看他attr的源码吧:

image.png

打开之后:

image.png

我们看他这个对外暴露的方法:

首先他通过this.node()获取dom对象,所以之前我重写的方法里面的this拿到的是d3获取的selection对象,需要将其转为DOM对象;

然后d3的这个方法里面,判断参数个数小于2的时候(那就是1咯),执行getter方法获取属性值,这个没有异议;

针对setter,为了支持对象型参数,并实现批量添加属性

于是,添加了如下代码:

image.png

然后,验证一下(为h1添加两个属性):

image.png

image.png

结果只有第一个获得了两个属性,一方面验证我之前添加的代码是没有问题的,一方面验证selectAll()并不能不会循环执行后续操作,但想到之前绑定数据之后的text()是可以实现循环赋值的,那么:

image.png

image.png


至此,便可以愉快地批量添加属性了。不用像网上教程那样,千篇一律的多重attr()操作:

image.png


但是!重点来了,以上简单的修改,不难发现只支持字符串型属性值,d3可是支持函数型属性值得啊,不用怕,后续我也针对函数型属性值作了补充:

image.png

页面使用:

image.png

页面展示:

image.png

至此,这个函数应该算是比较完善了,反正我用得挺顺手

注:

我们现在的HTML都是通过DOCTYPE来声明,XHTML中有xmlns声明,svg标签也是有的,d3中有删除通过命名空间和名称指定的属性的方法,但是我们现在写的时候,都不需要添加命名空间,所以我修改的方法就没有添加removeAttributeNS()支持了,最终版:

image.png

posted @ 2018-11-12 13:15  桔子桑  阅读(3237)  评论(1编辑  收藏  举报