为什么ng-src不会触发AngularJS中的某些属性更改?

时间:2013-10-04 02:04:56

标签: javascript angularjs angularjs-directive

我有一个示例指令,用于监视元素的变化,例如offsetWidth。

如果我将指令应用于通过src属性加载url的img元素,那么一切正常。

如果我将指令应用于通过ng-src属性加载url的img元素,则offsetWidth不会更新。

HTML:

<!DOCTYPE html>
<html ng-app="test">

  <head>
    <script data-require="angular.js@1.2.0-rc2" data-semver="1.2.0-rc2" src="http://code.angularjs.org/1.2.0-rc.2/angular.js"></script>
    <script src="script.js"></script>
  </head>

  <body>
    <h1>OffsetWidth: {{offsetwidth}} OffsetLeft: {{offsetleft}}</h1>
    <img testing ng-src="{{'http://scienceblogs.com/scientificactivist/wp-content/blogs.dir/392/files/2012/04/i-dcb85296b3695e8ce6d1ae4d660cea30-Smiley-face.gif'}}"></img>
  </body>

</html>

使用Javascript:

angular.module('test', []).
  directive('testing', function() {
    return function(scope, element, attr) {
      scope.$watch(
        'element.offsetWidth',
        function(newVal, oldVal) {
          scope.offsetwidth = element[0].offsetWidth
        }
      )
      scope.$watch(
        'element.offsetLeft',
        function(newVal, oldVal) {
          scope.offsetleft = element[0].offsetLeft
        }
      )
    }
  });

Plunkr

更新

我在下面应用了Buu Nguyen的解决方案,以确保正在观察正确的更改,但似乎存在时间问题。当多次重新加载页面时,我注意到有时值会正确更新,有时则不会。

更新了javascript:

angular.module('test', []).
  directive('testing', function() {
    return function(scope, element, attr) {
      scope.$watch(
        function() {
          return element[0].offsetWidth
        },
        function(newVal, oldVal) {
          scope.offsetwidth = element[0].offsetWidth
        }
      )
      scope.$watch(
        function() {
          return element[0].offsetLeft
        },
        function(newVal, oldVal) {
          scope.offsetleft = element[0].offsetLeft
        }
      )
    }
  });

Updated Plunkr

3 个答案:

答案 0 :(得分:1)

您无法观看element的属性,因为它不在范围内。修复此问题而不用不必要的字段污染范围的一种方法是将监视功能传递给$watchDemo link

angular.module('test', []).
  directive('testing', function() {
    return function(scope, element, attr) {
      element.on('load', function() { 
        scope.offsetwidth = element[0].offsetWidth
        scope.offsetleft = element[0].offsetLeft
        scope.$apply();
      });
    }
  });

注意:img的{​​{1}}事件可能无法在所有浏览器中可靠地运行。要获得更强大的方法,请尝试使用此library

答案 1 :(得分:0)

跟随Buu Nguyen的回答,这是正确的,我应该说不建议使用观察者来监控DOM,因为the Angular docs在“Scope $ watch Performance Considerations”部分下说明:

  

脏的检查属性更改的范围是一个常见的操作   Angular,因此必须使用脏检查功能   高效。应该注意脏检查功能   不进行任何DOM访问,因为DOM访问速度要慢几个数量级   然后在JavaScript对象上进行属性访问。

我不确定在你的情况下这是否会成为一个问题,但要记住它。

答案 2 :(得分:0)

我只是猜测,但可能是你的指令在ng-src之后运行,因此它没有接收到更改,因为它及时错过了它(考虑到图像在浏览器缓存中)。指令的默认优先级为0,但ng-src有99,因此尝试将测试指令分配给高于99的优先级不会有什么坏处。