3

我有一个示例指令来监视元素的变化,例如 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
        }
      )
    }
  });

更新了 Plunkr

4

3 回答 3

1

您无法查看 的属性,element因为它不在范围内。解决此问题而不用不必要的字段污染范围的一种方法是将 watch 函数传递给$watch. 演示链接

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'load事件可能无法在所有浏览器中可靠地工作。要获得更强大的方法,请尝试此

于 2013-10-04T02:15:14.907 回答
0

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

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

我不确定这是否会成为您的问题,但请记住这一点。

于 2013-10-04T02:32:25.260 回答
0

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

于 2013-10-04T22:24:39.277 回答