2017-08-16 55 views
1

我是AngularJS的新手,有一個問題,我希望有人能指出我正確的方向來搞清楚。我創建了一個名爲sizeWatcher的指令,該指令作爲一個屬性放置到HTML中,它基本上只是獲取其所在元素的高度,並將該高度反饋到名爲style的作用域變量中,該變量通過使用ng-style="style"設置到另一個元素上。角度指令多次觸發

我發現無論何時我打開手風琴,$watch都會觸發該指令,但它會發射多次。我有一個console.log在我的$watch,我看到3個日誌條目,前兩個是相同的(猜測這發生在手風琴打開前點擊,然後手風琴打開,第三個日誌條目是手風琴打開後的最終高度)。主要問題是style變量在手風琴被展開之前只能設置到較小的高度,即使日誌在最後一次命令被擊中時記錄的高度更高 - 我怎樣才能忽略第一個事件觸發和只有在指令的最後一次和最後一次執行時才採取相應措施?任何洞察到這一點將不勝感激。下面的相關代碼附:


模板:

<div class="content-wrap" id="height-block" ng-style="style"> 
    <!-- Other HTML etc... --> 
    <uib-accordion size-watcher close-others="oneAtATime"> 
      <!-- Accordion Directive HTML.. --> 
    </uib-accordion> 
</div> 

的JavaScript:

.directive("sizeWatcher", function() { //add size-watcher attribute to element on the page to have it echo its' height to the {{style}} scope 
    function link(scope, element, attrs) { 
     scope.$watch(function() { //watch element for changes 
      var height = element[0].offsetHeight; 
      console.log(height); 
      if (height > 150) { 
       scope.style = { 
        height: height + 'px' 
       }; 
      } 
     }); 
    } 
    return { 
     restrict: "AE", //attribute & element declarations 
     link: link 
    }; 
}) 

回答

2

我怎麼能忽略第一個$手錶事件解僱,只有在最後一幕 相應並最終貫徹指令?

可以忽略觀察家當新的或舊的值undefined,而不是彼此相等:

$scope.$watch(function() { 
    return element.height(); // or something else 
}, 
function (newVal, oldVal) { 

    if (newVal !== undefined && oldVal !== undefined && newVal !== oldVal) { 
     // your stuff 
     if (newVal > 150) { 
      scope.style = { 
       height: newVal + 'px' 
      }; 
     }  
    }     
}); 

反正你可以玩if語句問候您的需求


FYI ,以提高性能$watch返回取消回調,因此您可以隨時停止觀察者:

var cancelWatch = $scope.$watch(function() { 
    return element.height(); 
}, 
function (newVal, oldVal) {   
    if (<some condition>) {    
     cancelWatch();    
    }   
}); 
0

顯然回答這個需要鏈接到Angular-Documentation for $watch

它指出以下:

後觀察者與範圍登記時,listener FN異步調用(經由$evalAsync)初始化觀察者。在極少數情況下,這是不可取的,因爲當watchExpression的結果沒有改變時調用監聽器。要在listener fn內檢測到這種情況,可以比較newValoldVal。如果這兩個值相同(===),則由於初始化而調用偵聽器。

這可能解釋你的第一個電話。

我猜測第二次調用發生是因爲手風琴在初始化(帶有標題/或標籤或任何東西)後會被重新觸發,從而在高度上觸發$digest以及因此$watch表達式。

最後,第三次調用發生在打開手風琴並且高度實際發生變化時。

要解決這個問題,您可以比較Maxim Shoustin在他的回答中所說的觀察表達式的newValue和oldValue。下面是一個例子(再次從角文檔拍攝)

scope.$watch(
    // This function returns the value being watched. It is called for each turn of the $digest loop 
    function() { return food; }, 
    // This is the change listener, called when the value returned from the above function changes 
    function(newValue, oldValue) { 
    if (newValue !== oldValue) { 
     // Only increment the counter if the value changed 
     scope.foodCounter = scope.foodCounter + 1; 
    } 
    } 
); 

但是,如果你真的想改變,你可能想看看進入ng-class元素的風格,而不是手動註冊任何觀察家!

0

這是因爲你不使用$看正確的方式發生,

  • 的第一個參數$表是你想要觀看一個變量(這可能是一個回調)。
  • 的第二個參數$手錶,其對改變

所需的操作所以你的情況會是這樣的

scope.$watch(
    function() { 
     return element[0].offsetHeight; 
    }, 
    function() { //watch element for changes 
     var height = element[0].offsetHeight; 
     console.log(height); 
     if (height > 150) { 
      scope.style = { 
       height: height + 'px' 
      }; 
     } 
    } 
) 

請注意第一功能的回調,所以每當它返回的值發生變化,第二次回調將執行

希望這會對您有所幫助