因為習慣了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()支持了,最終版: