2017-08-16 80 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' 
      }; 
     } 
    } 
) 

请注意第一功能的回调,所以每当它返回的值发生变化,第二次回调将执行

希望这会对您有所帮助