简体   繁体   English

角度$ watch细微差别和工厂不反映状态变化吗?

[英]Angular $watch nuance and factory not reflecting state change?

I have difficulty grasping why the factory will not reflect changes to its primitives (as a singleton) but it will to objects.. sometimes.. in the following six scenarios. 我很难理解为什么工厂在以下六种情况下不会将对原语的更改(以单例形式)反映为对象,但有时会向对象反映。

I have this factory: 我有这个工厂:

angular.module('my.module).factory('myfactory', FactoryFunction);
function FactoryFunction(){

  var primitiveVariable = false;
  function togglePrimitive(){
    primitiveVariable = !primitiveVariable
  }
  var dummyObject = {
    isTrue = false;
  }
  function toggleObject(){
    dummyObject.isTrue = !dummyObject.isTrue;
  }
  var myFactory = {
    toggleObject: toggleObject,
    dummyObject: dummyObject,
    togglePrimitive: togglePrimitive,
    primitiveVariable: primitiveVariable
   }
   return myFactory
}

and I also have this directive 我也有这个指令

angular.module('my.module).directive('myDirective', DirectiveFunction);
DirectiveFunction.$inject['myFactory'];
function DirectiveFunction(){
  return {
    restrict: 'A',
    scope:{},
    link: function(scope, element, attributes, nullcontroller, nulltranslcude){

      //watch1 WONT RUN 
      //watched is undefined even if myFactory.togglePrimitive() runs
      scope.$watch(myFactory.primitiveVariable, function(){
        //do stuff
      });

      //watch2 WONT RUN
      //watched is undefined even if myFactory.togglePrimitive() runs
      scope.$watch(function(){return myFactory.primitiveVariable}, function(){
        //do stuff
      });

      //watch3 WONT RUN
      //not returning something by calling togglePrimitive()?
      scope.$watch(myFactory.togglePrimitive(), function(){
        //do stuff
      });

      //watch4 WILL RUN
      //but now I am not even running the function...?
      scope.$watch(myFactory.togglePrimitive, function(){
        //do stuff
      });

      //watch5 WONT RUN
      scope.$watch(myFactory.dummyObject.isTrue, function(){
        //do stuff
      });

      //watch6 WILL RUN 
      //... seriously??
      //is myObj.val and function(){return myObj.val} NOT the same?
      scope.$watch(function(){return myFactory.dummyObject.isTrue}, function(){
        //do stuff
      });
    }
  }
}

My question is, why do watch1, watch2, watch3, watch5, NOT work while watch4, wantch6 DO work? 我的问题是,为什么watch1,watch2,watch3,watch5在watch4,wantch6不能工作?

I am interested in the why this happens. 我对为什么会这样感兴趣。 Is this a design choice? 这是设计选择吗? what is the purpose? 什么目的?

Also I would like to add that function(){ return myFactory.primitiveValue } does not work as a watch expression and yet function(){ return myFactory.dummyObject.isTrue } works as a watch expression. 我也想补充一点,function(){return myFactory.primitiveValue}不能作为监视表达式,而function(){return myFactory.dummyObject.isTrue}可以作为监视表达式。 Does anyone know why this bias occurs between primitive vs object's primitive attribute? 有谁知道为什么这种偏见发生在原始对象与对象的原始属性之间? They are both primitives. 它们都是原语。 When console.log from the factory function that updates the primitive, it reflects the change. 当来自工厂功能的console.log更新原语时,它反映了更改。 When console.log from the expression that returns the primitive (in the $watch), it does not reflect the change. 当表达式中的console.log返回原语(在$ watch中)时,它不反映更改。

jsFiddle: https://jsfiddle.net/b0svnjqf/21/ jsFiddle: https ://jsfiddle.net/b0svnjqf/21/

Any light anyone can shine into this I would greatly appreciate it. 任何人都可以照到的光,我将不胜感激。

That is because watch expression takes either a string representing the property or an expression that can be evaluated on that scope or a function getter that returns a value which is used for dirty checking every digest cycle. 这是因为watch表达式采用表示属性的字符串或可以在该作用域上求值的表达式,或者采用返回值的函数getter,该值用于每个摘要周期的脏检查。

So for example: 因此,例如:

  scope.$watch(myFactory.primitiveVariable, function(){
    //do stuff
  });

watch expression is the value of myFactory.primitiveVariable and not the property itself, where as: 监视表达式是myFactory.primitiveVariable的值,而不是属性本身,其中:

  scope.$watch(function(){return myFactory.primitiveVariable}, function(){
    //do stuff
  });

runs the expression getter passed in as function during every digest cycle for dirty check which will return the value of the property at that time. 在每个摘要循环中运行作为函数传入的表达式getter进行脏检查,这将在那时返回该属性的值。

Similarly when you do : 同样,当您这样做时:

  scope.$watch(myFactory.togglePrimitive, function(){
    //do stuff
  });

you are passing the reference to the function togglePrimitive as the watch expression which can be a getter but you are really not returning anything from there so your watch listener will not run after 1 iteration. 您将传递给函数togglePrimitive的引用作为watch表达式,它可以是一个getter,但实际上并没有从那里返回任何内容,因此您的watch listener不会在1次迭代后运行。

Documentation : 说明文件

watchExpression: function() | watchExpression:function()| string

Expression that is evaluated on each $digest cycle. 在每个$ digest循环上评估的表达式。 A change in the return value triggers a call to the listener. 返回值的更改会触发对侦听器的调用。

string: Evaluated as expression 字符串:作为表达式求值

function(scope): called with current scope as a parameter. function(scope):以当前范围为参数调用。

Apart from this there is no point changing the variable primitiveVariable and expect the change to be reflected magically in myFactory.primitiveVariable they both are different and as they are primitive they don't hold on to the references as well. 除此之外,没有任何必要更改变量primitiveVariable并希望将更改神奇地反映在myFactory.primitiveVariable它们两者都是不同的,并且由于它们是原始对象,因此也不会保留引用。

function FactoryFunction(){

  var myFactory ,
      dummyObject = {
         isTrue = false;
      };

  function togglePrimitive(){
    //Set the value directly on the factory instance
    myFactory.primitiveVariable = !myFactory.primitiveVariable
    //or even this.primitiveVariable  = !this.primitiveVariable;
    //But better not to assume "this" as much as you can
  }

  function toggleObject(){
     //This is fine as you are modifying property on the reference and the same reference has been set to the dummyObject property of myFactory
     dummyObject.isTrue = !dummyObject.isTrue;
     //or this.dummyObject.isTrue = !this.dummyObject.isTrue;
  }

  myFactory = {
     toggleObject: toggleObject,
     dummyObject: dummyObject, //this should be fine unless you overwrite the variable dummyObject itself
     togglePrimitive: togglePrimitive,
     primitiveVariable: false //Set the value directly
   }  

   return myFactory;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM