Hacker News new | past | comments | ask | show | jobs | submit login

We've been running with d3 instead of jQuery for almost 2 years. Some notes so far:

- d3.selectAll is more verbose than $() but in my opinion, that's not a bad thing as I try to minimize DOM selections anyways;

- transitions are another area where D3 really shines, for cases where you don't/can't use CSS transitions, like displaying a discreet popup status message.

- d3 data binding is oh so convenient, and that's where the real magic happens. Combined with a queueing system like postal.js, we pretty much have the same thinking model as React. The DOM is now an expression of the data, and D3's joins figure out what DOM elements need to be updated. It's slightly lower level than React, in that you specify what happens on enter/update/exit, but in terms of efficiency, it seems great (disclaimer: we haven't run benchmarks);

- if you happen to like CoffeeScript, D3 turns into a very elegant DSL that is consistent for DOM editing, styling and event handling. Here's a simple lightbox modal dialog:

    lightbox.shell = d3.select "body"
      .div "#shadebox"
      .style "opacity", 0
      .on "click", ->
        lightbox.removeLightbox()
        d3.event.stopPropagation()

    lightbox.body = lightbox.shell.append "div"
      .attr "id", "lightbox"
      .on "click", -> d3.event.stopPropagation()

    lightbox.showLightbox()
    return lightbox.body
- we've added a `.div` function that's shorthand for d3.append and automatically adds an id and/or class, to feel a bit more like Jade;

- one downside we found with D3 is that we can't just grab any jquery plugin and throw it in our app.




> - d3 data binding is oh so convenient, and that's where the real magic happens

It's great, but it has limitations. It only ever binds to a single `__data__` property on the DOM nodes (making it very very difficult to associate multiple sets of data through a single DOM tree) and which needs to be carefully re-bound to each sub-node if you wish to substitute the objects with new ones. And acting on the data (basically two-way binding) and then updating the d3 selection has to be done very carefully too.

I've run into many subtle errors that stem from this fairly primitive method of binding.

It probably could use some additional abstractions to make replaying updates on object replacement/modification easier.


D3 has nested selections that let you handle cases like this. The data for a single element can be an array, and if that element is a div (HTML) or g (SVG) you can do another join and bind those data to its children. More info: http://bost.ocks.org/mike/nest/

To "substitute the objects with new ones", do another join, pass a key function as the second argument if necessary, and use the enter/update/exit pattern.


You're not telling me anything new here. The point is that those data-binds only propagate if you perform all the same selections on your update as you did during enter stage. I reported this issue and they essentially said it can't be improved due to backwards-compatibility requirements[1]

And key functions are non-trivial to create if 1. you use d3.nest[2] (not to be confused with nested selections) 2. you modify the data in a way that changes the grouping 3. you try to match existing nodes back to the changed groupings. Key-based computation is insufficient for dynamically matching DOM nodes to changing sets.

Those two things aren't showstoppers. They just make the data-binding fairly brittle.

The thing that it's bound to a non-namespaced __data__ property is more problematic in my opinion since you always have to pay attention to not overwrite the datum with a different selection on any DOMnode, otherwise you will break callbacks that rely on the data. It basically requires a 1:1 correspondence for DOM to data on the whole subtree.

This makes decomposing the selections into separate steps difficult. I.e. building a base tree and then populating the leaves with a separate data set can easily end up overwriting the data bindings of the base tree. Again, it's possible to avoid these pitfalls but if __data__ had been namespaced it would be far less hazardous.

[1] https://github.com/mbostock/d3/issues/2034 [2] https://github.com/mbostock/d3/wiki/Arrays#-nest




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: