Draconar
Draconar

Reputation: 1195

Should "ng-src" always be used, even without interpolation ?

In my angularjs project I need to go back and forth using both ng-src and src attributes in my tags.

Some images are static assets and will never change (they may be conditionally displayed) while other images are dynamic and dependent on scope variables.

May I use the mix of ng-src and src whenever I see fit?

I'm asking that because I once read that I should always use ng-src when working with angularjs, but I'm also afraid that I'm going to create bindings and watches that are really not necessary...

Upvotes: 2

Views: 838

Answers (1)

Ilan Frumer
Ilan Frumer

Reputation: 32367

always using ng-src ?

  • I don't see any reason using ng-src without interpolation.
  • @Vojta Jína says: "watching attributes only makes sense, if you interpolate them"
  • The documentation says: "Using Angular markup like {{hash}} in a src attribute doesn't work right"
  • It not says using src in angular.js is not right...!
  • Same case with ng-href.
  • using ng-src without interpolation will probably not cause performance issues.
  • If you hit performance I guess ng-repeat is guilty.

does ng-src always creates bindings?

Actually the source code is pretty straightforward https://github.com/angular/angular.js/blob/v1.2.7/src/ng/directive/booleanAttrs.js

ng-src will always $observe your attributes.

// ng-src, ng-srcset, ng-href are interpolated
forEach(['src', 'srcset', 'href'], function(attrName) {
  var normalized = directiveNormalize('ng-' + attrName);
  ngAttributeAliasDirectives[normalized] = function() {
    return {
      priority: 99, // it needs to run after the attributes are interpolated
      link: function(scope, element, attr) {
        attr.$observe(normalized, function(value) {
          if (!value)
             return;

          attr.$set(attrName, value);

          // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
          // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
          // to set the property as well to achieve the desired effect.
          // we use attr[attrName] value since $set can sanitize the url.
          if (msie) element.prop(attrName, attr[attrName]);
        });
      }
    };
  };
});

As for $observe, from the documantation:

The observer function will be invoked once during the next $digest following compilation. The observer is then invoked whenever the interpolated value changes.

Or more Simple, if there is no interpolation there is no dirty checking. AFAIK, all performance issues angular.js has with (lots of) bindings is when it does dirty checking.

Looking further inside compile.js:

// no one registered attribute interpolation function, so lets call it manually

  • If there is no interpolation we end up invoking the callback only once.
  • In the case of ng-src you can see above the callback that $observe registers.
  • If there is an interpolation then angular will register a $watch (dirty checking) like so $watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {

Conclusion

  • use src when there is no interpolation
  • use ng-src when there is an interpolation
  • using ng-src without interpolation will end up running the callback only once. means it has subtle impact to performance.
  • Another issue is that images will not start loading until angular is bootstraped or in case you use routes (who's not?) until your views are compiled. This could a have a significant impact on load times.

Upvotes: 3

Related Questions