2013-10-04 58 views
3

我有一個示例指令,監視元素中的更改,如offsetWidth。爲什麼ng-src在AngularJS中不觸發某些屬性更改?

如果我申請指令到通過src屬性加載的URL的img元素,一切工作正常。

如果我申請的指令來加載通過NG-src屬性的URL的img元素,offsetWidth沒有更新。

HTML:

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

    <head> 
    <script data-require="[email protected]" 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

UPDATE:

我申請以下布歐Nguyen的解決方案,以確保正確的變化是w ^但是,似乎存在時間問題。當多次重新加載頁面時,我注意到有時值會正確更新,有時不會。

更新的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

回答

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(); 
     }); 
    } 
    }); 

注:imgload事件可能不會在所有瀏覽器可靠地工作。要獲得更健壯的方法,請嘗試使用library

+0

有趣的優先級更高。那之前它是如何工作的?調用'element.offsetLeft'來觀察是返回正確的值,所以它似乎正在評估正確的範圍。 –

+0

如果不在範圍內,範圍無法通過字符串表達式進行觀察。然而,監聽器總是初始化一次初始值(如果你想知道爲什麼,請閱讀文檔或代碼),所以一些幸運的時機可能會讓你的原始代碼在特定的時間點對某些屬性起作用,但是這並不「這意味着它是正確的代碼。 –

+0

很容易驗證,而不是在偵聽器內使用'element [0] .offsetLeft',而是使用'newVal'。我相信它會是'undefined'。 –

0

跟進布歐阮的答案,這是正確的,我應該說,這是不建議使用觀察者來監視DOM,如the Angular docs狀態「範圍$腕錶性能注意事項」部分:

髒檢查屬性更改範圍是 角一種常見的操作,爲此髒檢查功能必須 效率。應當注意的是,骯髒的檢查功能不 沒有做任何DOM訪問,訪問DOM是JavaScript對象的幅度較慢 然後屬性訪問訂單。

我不確定這是否會成爲您的案例中的問題,但請記住。

+0

我可以用其他方式監視DOM嗎?如果我的意圖是讓指令根據頁面上呈現的元素的當前大小和位置來執行某些操作,那麼您會提出什麼建議? –

+0

我之前在Angular中沒有做過這樣的事情,所以我沒有一個直接的答案。什麼呈現元素?您的指令是否可以這樣做,以便它知道元素的大小和位置,而無需監視這些屬性? –

0

我只是猜測,但它可能是你的NG-SRC後指令運行等,因爲它錯過它的時候它不拿起變化(考慮到圖像是瀏覽器緩存)。對於指令默認優先級爲0,但NG-SRC有99所以它不會傷害嘗試和分配您的測試指令超過99

相關問題