There are two things to take into consideration when we talk about Angular’s performance. As we mentioned previously, Angular 1.x and higher relies on two-way data binding. This concept is based on “dirty checking,” a mechanism that can make our AngularJS application laggy.
When we bind values in HTML with our model, Angular creates a watcher for each binding to track changes in the DOM. Once the View updates (becomes “dirty”), Angular compares the new value with the initial (bound) value and runs the $digest loop. The $digest loop then checks not only values that have actually changed but also all others values that are tracked through watchers. This is why performance will decrease a lot if your application has too many watchers. This drawback is even more painful when several values (Views) are dependent on each other. Once Angular sees that the change of a value was triggered by another change of a different value, then it stops the current $digest cycle and runs it all over again.
The loop doesn’t stop working until it checks all watchers and applies all necessary changes to both the View and the Model. In practice, we can bind an <input> field to different Views and Models. When the user enters new data into the field, the change may not be immediately visible. It’s better to avoid that.
Another shortcoming of the AngularJS framework is the way it works with the DOM. Unlike React, AngularJS applies changes in the real DOM in the browser. When the real DOM gets updated, the browser has to change many internal values to represent a new DOM. This also has a negative impact on application performance.
Poor performance is the main reason why Angular 2 supporters introduced the virtual Document Object Model rendered on the server and one-way data binding similarly to React. Still, Angular 2 offers two-way data binding as an option.