This is inspired by a blog post by Yehuda Katz on how the Glimmer engine works. The following is an idea for a faster view layer based on my interpretation of how Glimmer works. I could be wrong, but I think the idea is solid either way.
The key takeaway that I have is the advantage of separating out getting the value of a binding from determining when the value changes. For example, say you had a template like:
Instead of providing it an Observable that sends events when name
is changed, instead the view engine provides 2 interfaces; one for getting a value and another for notifying the view engine that a property has changed. This would enable providing plain objects to the view layer like:
{
"name": "world"
}
And then a notifier API that might be something like:
view.update("name");
Or something like that. Here's where I stop understanding what Glimmer is doing. It is using opcodes to make its updates faster. I'm not sure why it is doing this or in what way it helps. Nevertheless, you can imagine a simpler implementation that looks up a binding by the key provided by view.update(key)
, gets the current value using var currentValue = viewModel.name
, checks against a cached value, and updates any bindings.
There are two advantages I see to this approach:
- It avoid all of the work needed to set up an Observable object and all of the work needed to trigger events. This means that initial renders should be much faster if using plain objects.
- By separating out getting a value from figuring out when the value changes, it allows different types of data to be used for the ViewModel. The ViewModel might be an Observable. Or it might be a plain object, a plain class instance, or some other type. This would allow for using CanJS with Redux and other systems not based on Observables.
The disadvantage is that by pushing change detection into the view layer, I'm not sure how something like a compute would work.
This might be where the opcode engine comes into play. Since you can't rely on events to trigger compute changes, instead you have to check the current value of everything in the template. This could be expensive. What the VM might be doing here is making it quicker to figure out where to stop checking values. For example let's say you had:
Let's say that isAdmin
is computed somehow (maybe it's a regular function). Let's say we got a notification like:
view.update("isSuperAdmin");
We can avoid checking isAdmin
at all. And we can avoid checking name
if isSuperAdmin
value remains the same.
The disavantage here is that we potentionally will be checking values (and therefore calling functions) that haven't changed. However we can stop when we get to a section whose value hasn't changed (we don't need to check any values below that point).