Angular 1.3 shipped with an awesome new performance enhancing feature - one-time binding. What does this mean for us Angular developers and the performance of our apps? A lot! For us developers, adoption is really simple, and the performance gains for our apps are huge.
Let’s look at the problem really quick, starting with the $digest
cycle. The $digest
cycle is essentially a loop through all our bindings which checks for changes in our data and re-renders any value changes. As our apps scale, binding counts increase and our $digest
loop’s size increases. This hurts our performance when we have a large volume of bindings per application view. So what can we do to optimise this?
Table of contents
Thankfully, Angular 1.3 has put a lot of effort into performance, so we can utilise their new syntaxes and APIs to build faster apps.
What does it mean?
One-time binding is very simple, from the docs: One-time expressions will stop recalculating once they are stable, which happens after the first digest if the expression result is a non-undefined value.
In a nut shell, when we declare a value such as {{ foo }}
inside the DOM, once this value becomes defined, Angular will render it, unbind it from the watchers and thus reduce the volume of bindings inside the $digest
loop. Simple!
Free eBook
Directives, simple right? Wrong! On the outside they look simple, but even skilled Angular devs haven’t grasped every concept in this eBook.
- Observables and Async Pipe
- Identity Checking and Performance
- Web Components <ng-template> syntax
- <ng-container> and Observable Composition
- Advanced Rendering Patterns
- Setters and Getters for Styles and Class Bindings
The Syntax
The syntax is actually very simple, typically we’re used to seeing something like this:
<p>
{{ vm.user }}
</p>
The new syntax adds ::
in front of any values, which declares we want one time binding:
<p>
{{ ::vm.user }}
</p>
Once vm.user
becomes defined and contains a value, Angular will unbind it and any Model updates won’t affect the View. A simple example is if we did this:
<input type="text" ng-model="vm.user">
<p>
{{ ::vm.user }}
</p>
Anything typed into the input wouldn’t render the Model value out in the View, consider it a “render-once” type method rather than bind once.
Code examples
We already covered a simple example above using curly handlebars, we can also use it for things such as ng-if
:
<div ng-if="::vm.user.loggedIn"></div>
This helps us serve and maintain specific pieces of functionality on the front-end that we might want to simply destroy permanently based on a user’s role or state (for example).
Let’s see ng-class
:
<div ng-class="::{ loggedIn: vm.user.loggedIn }"></div>
Runs once, again great for initial states.
My favourite is still on the ng-repeat, instead of constructing our own navigation (for example) or using an ng-repeat
without one-time binding, we’re going to be doing extra work or have our binding count higher when we really don’t need it to be.
The syntax is pretty simple inside an ng-repeat
:
<ul>
<li ng-repeat="user in ::vm.users"></li>
</ul>
Once the ng-repeat
is populated, we’re all set and everything is unbinded.
Syntax is pretty simple, albeit a little “weird”, but after using it in production it sure helps other developers to know what’s binding once.