在绑定资源加载异步时,在函数中包装$ watch / $ timeout会中断双向绑定

时间:2014-08-28 19:52:34

标签: javascript angularjs angularjs-directive angularjs-scope

TL; DR Check the example

我有一个带有隔离范围的指令,其范围如下所示:{ obj: '=' }。然后我需要将该值应用于模型属性:

link (scope, element, attrs) {
  scope.model = {};
  scope.model.v = scope.obj.value;
}

然后我需要确保在scope.model.value更改时,父范围的属性也会更新。所以我做了这样的事情:

scope.$watch('obj.value', function (a,b) {
  if (!angular.equals(a, b)) {
    $timeout(function () {
      scope.model.v = a;
    });
});

反之亦然,在另一个方向上绑定。

这很有效,但我想把它放在一个可重用的函数中,所以我并不总是重复那段代码。

所以我想出了这个:

/**
 * scope: the scope being altered
 * a:     string representing the first property being bound
 * b:     string representing the second property being bound
 * objEq: boolean to be passed to the scope.$watch object equality argument
 */
var bind = function (scope, a, b, objEq) {
    objEq = typeof objEq === 'undefined' ? false : objEq;

    var getPointer = function (s) {

      var parts = s.split('.');
      var pointer = scope;
      var key = parts.slice(-1);

      for (var i = 0; i < parts.length-1; i++) {
        var part = parts[i];
        pointer = pointer[part];
      }

      return {pointer: pointer, key: key};
    };

    var aObj = getPointer(a);
    var bObj = getPointer(b);

    scope.$watch(a, function (n, o) {
        if (!angular.equals(n, o)) {
            $timeout(function () {
                bObj.pointer[bObj.key] = n;
            });
        }
    }, objEq);

    scope.$watch(b, function (n, o) {
        if (!angular.equals(n, o)) {
            $timeout(function () {
                aObj.pointer[aObj.key] = n;
            });
        }
    }, objEq);
};

如果父作用域的属性被硬编码到控制器中,则此方法很有用,但如果属性是http请求的结果,则会中断。我无法弄清楚这里发生了什么。有人可以解释一下吗?

Here is an example.


此外,仅将scope.$watch包裹在一个函数中并不会破坏它。

这有效:

function (scope, a) {
  scope.$watch(a, function (n, o) {
    if (!angular.equals(n, o)) {
      $timeout(function () {
        scope.otherProperty = n;
      });
    }
  });
}

1 个答案:

答案 0 :(得分:0)

好的,我想出了一个解决方案,感谢@ PSL对出现问题的解释。

我只需要在getPointer内调用scope.$watch函数。

scope.$watch(a, function (n, o) {
  if (!angular.equals(n, o)) {
    var bObj = getPointer(b);
    $timeout(function () {
      bObj.pointer[bObj.key] = n;
    });
  }
}, objEq);

例子: jsfiddle plunker