$watch 监控指令延迟 1 个周期时的类变化 [英] $watch to monitor change in class on directive firing 1 cycle late

查看:22
本文介绍了$watch 监控指令延迟 1 个周期时的类变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标是在特定指令通过 ng-class 接收到focused"类时执行一些操作.但是观察每个指令的变化似乎在做我不明白的奇怪的事情.首先是代码:

My goal is to do some action when a particular directive receives the class 'focused' through ng-class. But watching for changes on each of the directives seems to be doing weird things I don't understand. Here is the code first:

http://plnkr.co/edit/6Te8O2mlBI058DpwGF7f?p=preview

index.html

   <test-question
      ng-class="{'focused': tracer.focus == 1}"
      focusnum = "{{n}}"
      ng-click="tracer.focus = 1"
      >
      Test Question 1
    </test-question>
    <test-question
      ng-class="{'focused': tracer.focus == 2}"
      focusnum = "{{n}}"
      ng-click="tracer.focus = 2"
      >
      Test Question 2
    </test-question>
    <test-question
      ng-class="{'focused': tracer.focus == 3}"
      focusnum = "{{n}}"
      ng-click="tracer.focus = 3"
      >
      Test Question 3
    </test-question>

script.js

angular.module('sampleApp', [])
  .controller("SampleController", function($scope) {
    $scope.tracer = {
        focus: 1
    }
  })
  .directive('testQuestion', function() {
    return {
        restrict: 'E',
        link: function($scope, el, attrs) {
          $scope.$watch(function() {
                  return el.attr('class');
              }, function(newValue, oldValue) {
                  // do something here when directive gets class focused
                  console.log("text", el.text());
                  console.log("newValue", newValue);
                  console.log("oldValue", oldValue);
            });
        }
    }
  });

首先突出显示第一个测试问题.当您单击第二个问题时,我希望控制台记录

Initially the first test question is highlighted. When you click the second question I expect the console to log

text"测试题1新值"未定义"oldValue" 聚焦文字"测试题2新价值"聚焦"oldValue" 未定义

但是控制台实际上记录了

However the console actually logs

text"测试题1新价值"聚焦"oldValue" 未定义

因此,对于这种奇怪的行为,我无法准确检测指令何时接收到重点关注的类.手表好像晚了一个周期.如果一位朋友能帮助我理解为什么会发生这种情况,那就太好了.谢谢!

附加

在我点击问题 2 之后,如果我随后点击问题 3,控制台会记录

After I click question 2, and if I subsequently click question 3 the console logs

text"测试题1新价值""oldValue" 聚焦文字"测试题2新价值"聚焦"oldValue" 未定义

推荐答案

是的,已经晚了,目前还没有合适的解决方案.不过你可以在下面做一些事情.

Yes is become late, there is no proper solution for this condition yet. However you can do something below.

    $scope.$watch(function() {
              return el.hasClass('focused');
          }, function(newValue, oldValue) {
              // now you should use javascript setTimeout for check after $diggest
              var myOldValue = newValue; //this mean newValue realy oldValue yet.
               setTimeout(function(){
                 var myNewValue= el.hasClass('focused');
                  console.log(myNewValue, myOldValue)
                  //do staff here
               },0)
              //note that, don't use angular $timeout it may couse recursive stack
        });

为什么?

因为您正在观看 AngularJS 之外的异步事件.即需要在最后调用,通过 $scope.$apply() 告诉 AngularJS 一个异步事件刚刚发生.

Because you are watching an async event which outside of AngularJS. Namely need to called at the end, to tell AngularJS that an asynchronous event just occurred by using $scope.$apply().

这就像我们自定义的 $('button').on('click', ...) 事件,需要 $scope.$apply().但是您可能会问,我正在观察使用 ng-class 所做的更改.这是正确的,但您的观察者函数在 ng-class 完成其工作之前被调用.也就是说,您不是在看ng-class",而是在看 class 属性.出于这个原因,您正在聆听的更改将在下一个摘要中注意到 angular.

This like our custom $('button').on('click', ...) events which need to $scope.$apply(). However you may ask that, I am watching changes done by using ng-class. This is rigth, but your watcher function is called before ng-class done its work. Namely you aren't watching "ng-class" you are watching class attribute. For this reason the changes you are listen will noticed to angular in the next diggest.

如果你试图在你的观察者中访问当前类,你会得到旧值,因为 ng-class 还没有完成它的工作.

If you tried to access current class in your watcher, you will get old value, because ng-class hasn't done its work yet.

如果您尝试在观察者中访问当前类的 javascript setTimeout 函数,您将获得正确的值,因为 setTimeout 将在所有角度工作完成后调用.

If you tried to access current class javascript setTimeout function in your in your watcher, you will get the correct vallue, because setTimeout would be called after all angular works done.

这种情况适用于 AngularJS 之外的所有更改.当您尝试查看元素高度、宽度、颜色、对象属性等时.您可以安静地使用它.

This case is valid for all changes outside of AngularJS. When you tried to watch an element heigth, width, color, an object property etc. You can use it in quietness.

注意 认为在 AngularJS 之外观察变化就像一个承诺,而 setTimeout 将是你的回调.

NOTE Think watching changes outside of AngularJS like a promise and setTimeout would be your callback.

这篇关于$watch 监控指令延迟 1 个周期时的类变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆