4 ms·
Rather than try to diff two DOM trees and optimize reconciliation, why not use one-way data binding and update exactly what has changed, with 0 reconciliation c
by Silhouette 10y ago
Rather than try to diff two DOM trees and optimize reconciliation, why not use one-way data binding and update exactly what has changed, with 0 reconciliation cost?
If all of your rendered HTML corresponds 1:1 with the underlying data model, there's no particular advantage to the declarative approach used by React.
However, once you start to have relationships in the underlying data, so DOM events in one place can affect the desired DOM content somewhere else, simple one-way data binding is not sufficient.
For example, suppose we have an HTML table that needs to be rendered from some underlying data structure in our JS. How do you do that with simple one-way data binding -- what are you binding to what, exactly? If you're managing the HTML directly, you need to allow for things like rows being added or removed, not just updating the content of an individual cell.
Now suppose that table also allows you to sort by different columns and filter so only certain rows are shown. Rendering the correct HTML now requires keeping track of the underlying data model and all of the UI-related state, with the actual rows to be shown affected by several different factors.
Now suppose the table is going to have many rows, and pagination is required in the markup and controls.
You certainly can handle all of the related events manually, but in order to keep the rendered HTML correct you now need to write code that understands each possible change in the underlying data and UI in every possible context, and the combinatorics can get quite unpleasant here.
The alternative that declarative rendering tools like React offer is that you can specify what your rendered table should look like in absolute terms, using whatever inputs need to be considered but ignoring the existing state of the DOM. You still need to consider however many factors you have that affect the rendering, which might still be somewhat complicated in a case like this, but at least you only need to consider them from a single, neutral starting point, not relative to every possible starting point.
- spankalee 10y agoI don't get how your table example justifies the need for such a complex rendering pipeline. There are plenty of template libraries that can optimally re-render a list/table after row insert/remove/move operations. Events generated by elements in rows can easily be associated with the proper data item. React doesn't own declarative templating, and if you only use one-way databinding, and re-render only what changes (again, plenty of template libraries do this), you get `v=f(d)` and efficient updates. Why the extra complexity?
- Silhouette 10y agoThe table was just an example. The point is that if you use a declarative rendering approach, any non-trivial rendered output you want to generate only needs to be specified once, relative to a neutral starting point. React certainly doesn't own the idea of declarative rendering, I agree, but what template libraries do you have in mind that offer that sort of functionality without either being limited to some specific case (tables, say), having questionable performance properties, or implementing the same sorts of techniques that virtual DOM-based libraries like React are using? Perhaps it would help if you could give some concrete examples of the libraries you are thinking of, and point at some documentation (or give your own example code) to show how they would handle the kinds of events I described in my post above more efficiently and/or with cleaner code than a library using declarative rendering and a virtual DOM such as React.
- jiaweihli 10y agoAre you thinking of computed properties? If so, there are many libraries that have solved this, e.g.: https://vuejs.org/guide/computed.html https://vuejs.org/guide/computed.html https://guides.emberjs.com/v2.3.0/object-model/computed-properties/ https://guides.emberjs.com/v2.3.0/object-model/computed-prop... When implemented using one-way data binding (as both of the examples do), this is more performant than DOM diffing.
- Silhouette 10y agoNo, I'm talking about arbitrary relationships in the underlying data model, such that arbitrary events from anywhere in the DOM can lead to arbitrary changes in rendering anywhere in the DOM. Computed properties of the kind you linked to, when then used to drive rendering via one-way data binding, are a common but relatively simple example. And yes, that sort of direct DOM manipulation is likely to be faster, often much faster, than DOM diffing in the cases it covers. The advantage of the more general diff-based libraries is their generality, not their rendering speed.
- 10y ago