ractivejs/ractive — pull request #816 by Rich-Harris (2014-06-15 17:29:14+00:00)
Title: Viewmodel part 2

**not ready for merge, PR raised for easy comparison/exploration**

This is a follow-up to #804. At present, a few dozen tests are failing, the work is still in progress.

Headlines:

* merge and splice operations are handled at a viewmodel level, where they belong. There is less duplicated data-binding logic in `ractive.merge()` and patched array mutator methods as a result. It will also make it easier to tackle #747.
* Mutating the viewmodel (via `ractive.set()`, or array mutators, or whatever) does not result in dependants being immediately notified of the change. Instead, the changes are noted (via `viewmodel.mark(keypath)`) and later *applied* (with `viewmodel.applyChanges()` - calling this is the responsibility of the runloop). This has certain important benefits - derivative changes (i.e. computed properties and evaluators) are assessed *before* changes are propagated, which eliminates the back-and-forth complexity that was previously required to ensure that the view reflected the up-to-date state of the model at all times.
* Previously, dependants were grouped by 'priority', which was designed to ensure that unnecessary lower-level DOM changes didn't take place before the higher level changes that made them unnecessary - for example, in the case of `{{#img}}{{/img}}`, ensuring that if we did `ractive.set('img', null)`, we didn't bother setting `src` to `''` before removing the element. This is efficient but relatively complex, and it meant that we had to fudge the semantics of 'priority' when dealing with computed properties, observers and so on. Now, dependants are grouped semantically (e.g. there's a `default` group, of mustaches in the template, but also `computed`, `observers`, and so on). We still need to take account of priority when notifying mustache dependants, otherwise we'll do unnecessary work - that's not yet implemented.
* Evaluators and computed properties don't have satellite `Reference` objects, with all the complex interactions they entail. Instead, they register *themselves* as viewmodel dependants, which turns out to be much more straightforward. (cc @jrajav)

More commits to come shortly...