角度$观察细微差别和工厂没有反映状态变化?

时间:2015-10-22 20:09:00

标签: javascript angularjs factory watch

我很难理解为什么工厂不会反映其原语的变化(作为单身人士),但是它会反对...有时......在以下六种情况下。

我有这个工厂:

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
}

我也有这个指令

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

我的问题是,为什么watch1,watch2,watch3,watch5,在watch4,wantch6 DO工作时不工作?

我对发生这种情况的原因感兴趣。这是一个设计选择吗?目的是什么?

另外我想补充一点,function(){return myFactory.primitiveValue}不能作为监视表达式使用,但是function(){return myFactory.dummyObject.isTrue}可以作为监视表达式使用。有谁知道为什么这种偏差发生在原始对象的原始属性之间?它们都是原始的。当来自更新基元的工厂函数的console.log时,它反映了更改。当来自返回基元的表达式(在$ watch中)的console.log时,它不反映更改。

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

任何人都可以发光,我会非常感激。

1 个答案:

答案 0 :(得分:1)

这是因为watch表达式采用表示属性的字符串或可以在该作用域上计算的表达式,或者是函数getter,它返回一个用于脏检查每个摘要周期的值。

例如:

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

watch表达式是myFactory.primitiveVariable的值,而不是属性本身,其中:

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

运行表达式getter在每个摘要周期中作为函数传入,用于脏检查,这将返回当时属性的值。

同样地:

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

您将对函数togglePrimitive的引用作为可以作为getter的监视表达式传递但是您实际上没有从那里返回任何内容,因此您的监听侦听器将在1次迭代后不会运行。

Documentation

  

watchExpression:function()|字符串

     

在每个$ digest周期计算的表达式。返回值的更改会触发对侦听器的调用。

     

string:评估为表达式

     

function(scope):以当前范围作为参数调用。

除此之外,没有必要更改变量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;
}