Angularjs 多次角度定向射击

Angularjs 多次角度定向射击,angularjs,Angularjs,我是AngularJS的新手,有一个问题我希望有人能给我指出正确的方向来解决。我已经创建了一个名为sizeWatcher的指令,该指令作为一个属性放入HTML中,它基本上只是获取它所放置元素的高度,并将该高度回显到名为style的范围变量中,我通过使用ng style=“style”将该高度设置到另一个元素上 我发现每当我打开手风琴时,$watch都会按指令启动,但会启动多次。我在我的$watch中有一个控制台。log,我看到了3个日志条目,前2个是相同的(猜测这发生在手风琴打开前的单击上,然后

我是AngularJS的新手,有一个问题我希望有人能给我指出正确的方向来解决。我已经创建了一个名为
sizeWatcher
的指令,该指令作为一个属性放入HTML中,它基本上只是获取它所放置元素的高度,并将该高度回显到名为
style
的范围变量中,我通过使用
ng style=“style”
将该高度设置到另一个元素上

我发现每当我打开手风琴时,
$watch
都会按指令启动,但会启动多次。我在我的
$watch
中有一个
控制台。log
,我看到了3个日志条目,前2个是相同的(猜测这发生在手风琴打开前的单击上,然后手风琴打开,第3个日志条目是打开手风琴后的最终高度)。主要问题是,
style
变量仅在手风琴展开之前设置为较小的高度,即使日志记录的是指令最后一次命中时的较大高度——我如何忽略第一个
$watch
事件触发,而仅在指令的最后一次和最后一次运行时采取相应的行动指令?如能对此有所了解,将不胜感激。相关代码附于下文:
模板:

 <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>
.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
    };
})
我怎么能忽略第一次$watch事件触发而只采取行动 因此,在指令的最后一次和最后一次运行时

当新值或旧值未定义且彼此不相等时,可以忽略观察者:

$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语句


仅供参考,为了提高性能,
$watch
返回取消回调,以便您可以随时停止watcher:

var cancelWatch = $scope.$watch(function () {
    return element.height();
},
function (newVal, oldVal) {        
    if (<some condition>) {            
        cancelWatch();            
    }        
});
var cancelWatch=$scope.$watch(函数(){
返回元素。高度();
},
函数(newVal,oldVal){
如果(){
取消手表();
}        
});

显然,要回答这个问题,需要一个指向;)的链接

它声明如下:

在向作用域注册观察程序后,异步调用
侦听器
fn(通过
$evalAsync
)初始化观察程序。在极少数情况下,这是不可取的,因为在
watchExpression
的结果没有更改时调用侦听器。要在
侦听器中检测此场景
fn,可以比较
newVal
oldVal
。如果这两个值相同(
==
),则由于初始化而调用了侦听器

这可能是你第一次打电话的原因

我猜发生第二个调用是因为手风琴在初始化(带有标题/或标签或任何东西)后会重新播放,这会触发
$digest
,从而触发高度上的
$watch
表达式

最后,当你打开手风琴时,第三次呼叫发生,高度实际上发生了变化

要解决这个问题,你可以比较被关注表达式的newValue和oldValue,就像Maxim Shoustin在回答中所说的那样。下面是一个示例(同样取自角度文档)



但是,如果您确实想要更改元素的样式,您可能需要查看一下,而不是手动注册任何观察者

发生这种情况是因为您没有正确使用$watch

  • $watch的第一个参数是要监视的变量(可以是回调)
  • $watch的第二个参数是一个回调,它对更改执行所需的操作
所以在你的情况下是这样的

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'
          };
      }
   }
)
请注意第一个函数,因此每当它返回的值发生更改时,第二个回调将执行

希望这对你有帮助

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