4

Specifically, I'm wondering how they update elements without using innerHTML. In the docs, they clearly state how they're better than other templating engines because they don't re-render with innerHTML (ctrl-f innerHTML -- sorry). I started poking through the source code but there's a LOT of it and was hoping that perhaps I could get a faster answer from you guys.

So far my guesses have been

  • The compiler converts {{test}} into something like <ng-bind>test</ng-bind> which the linker can update when data changes, but it doesn't seem like this is happening when I look at the DOM of a rendered Angular page. And also seems like it could interfere with a client's CSS and other javascript components external to Angular.
  • They actually are using innerHTML but they're just not re-rendering the ENTIRE DOM -- only a small snippet of it (perhaps the data inside some sort of custom <ng-bind></ng-bind> tag).
  • They're somehow removing and appending new elements ... bad guess I think.

If anyone knows I'd love to learn. Otherwise it's back to the source code for me.


EDIT New Guess

After thinking about it some more, I believe this might be what happens: Compiler swallows html, say something like

<p> 
  {{model}} 
  <div> 
    <p> Hello ! </p> 
  </div> 
</p>

And converts it to this:

<p class="ng-binding"> 
  {{model}} 
  <div> 
    <p> Hello ! </p> 
  </div> 
</p>

Then Angular can crawl through and index all angular text nodes ( {{model}} ) eg document.getElementsByClass('ng-binding')[0].childNodes[0]. Each stored node can then be associated by the linker with a scoped model $scope['model']. Each node can then be updated extremely quickly by setting node.nodeValue = $scope['somemodel] (simplified)` and voilà, technically no innerHTML'ing and lightning speed DOM updates.

vin
  • 823
  • 1
  • 10
  • 15
  • I highly recommend [How do I think in AngularJS](http://stackoverflow.com/questions/14994391/) in the Related links on the right. – Stephen P Aug 13 '13 at 00:52
  • @StephenP Whew! lots of good stuff there, thanks! Out of curiosity, I spent my weekend reimplementing some features of Angular -- I know I know, why reinvent a perfectly round wheel -- and I was particularly curious about the nitty gritty internals of this one. – vin Aug 13 '13 at 00:57
  • @vin, do you have your work posted anywhere? I'm trying to build a better understanding of the "how" in Angular, especially how it updates the dom. Would greatly appreciate learning from your code! – HelloWorld Aug 22 '15 at 18:11

1 Answers1

5

Rather than replacing the element itself, as innerHTML would do, Angular prefers to modify the properties of existing elements.

The ng-bind directive is actually a good example. It keeps a reference to the element and just updates its .text() as the $scope changes (source):

var ngBindDirective = ngDirective(function(scope, element, attr) {
  element.addClass('ng-binding').data('$binding', attr.ngBind);
  scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
    element.text(value == undefined ? '' : value);
  });
});

This doesn't necessarily mean Angular won't use innerHTML at times, especially when creating new content. But, it tries to avoid it when possible.

Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199