Angularjs $scope.$watch,但只用于ngChange事件?

Angularjs $scope.$watch,但只用于ngChange事件?,angularjs,angularjs-scope,Angularjs,Angularjs Scope,我想订阅ngChange事件,但是是从代码而不是从标记订阅。也就是说,给定一个$scope和一个可通过ngModel绑定的表达式,我想订阅绑定到该表达式的任何ngModel指令对该表达式所做的任何更改。这可能吗 比如: $scope.field = "hello"; $scope.onButtonClick = function() { $scope.field = "button clicked!"; } // this callback is only when the user ty

我想订阅ngChange事件,但是是从代码而不是从标记订阅。也就是说,给定一个$scope和一个可通过ngModel绑定的表达式,我想订阅绑定到该表达式的任何ngModel指令对该表达式所做的任何更改。这可能吗

比如:

$scope.field = "hello";
$scope.onButtonClick = function() {
  $scope.field = "button clicked!";
}

// this callback is only when the user types in an input bound to field
// not when they click the button with ng-click="onButtonClick()"
$scope.$watchNgChange("field", function() { 
  console.log("user caused field to change via a binding");
});

// this callback is called for both ngModel binding changes and onButtonClick.
$scope.$watch("field", function() {
  console.log("field was changed");
});

我不能只使用$watch,因为它将捕获所有更改,包括从数据库加载数据、从ng click回调以及从$watch回调为其他表达式启动的更改(在本例中,如果存在任何循环引用,那么$watch回调很容易进入无限循环,并在10个摘要周期后出错),谁知道还有什么。

首先,每当我尝试这样做时,结果都是一个坏主意-我只是在解决代码中的设计问题或业务逻辑中的逻辑问题。一般来说,代码不应该关心数据是如何更改的,而应该关心数据是否已更改

其次,$watch可以同时提供新旧值-这对我来说已经足够了。如果旧值不等于新值,我想更新相关的数据模型。如果新旧值相等,我想忽略更新

<>最后,您可以考虑使用您的路由解析来消除“数据库加载”,因为完全定位的数据可以传递到控制器中(假设您返回一个承诺)。
.

首先,任何时候我尝试这样做都是一个坏主意-我只是在解决代码中的设计问题或业务逻辑中的逻辑问题。一般来说,代码不应该关心数据是如何更改的,而只关心数据是否已更改

其次,$watch可以同时提供新旧值-这对我来说已经足够了。如果旧值不等于新值,我想更新相关的数据模型。如果新旧值相等,我想忽略更新

<>最后,您可以考虑使用您的路由解析来消除“数据库加载”,因为完全定位的数据可以传递到控制器中(假设您返回一个承诺)。
.

不要这样做,听起来像是在试图将DOM逻辑(例如,如果用户与DOM元素交互)引入控制器

如果您阅读ngChange指令的源代码,您会发现它需要一个ngModel,作为视图和控制器之间的桥梁

我建议您创建一个模型副本,并在视图中使用ngModel+ngChange将该副本用于数据绑定,然后您可以$watch该副本并执行任何您想要的操作

$scope.field = "hello"; //the field you care
$scope.fieldCopy = $scope.field; //use 'fieldCopy' for databinding
在html代码中,您可以使用多种方式更改模型fieldCopy

<input ngModel="fieldCopy" name='foo' />
<input ngModel="fieldCopy" name='foo2' />
如果要使fieldCopy与field保持同步,请添加另一个手表:

$scope.$watch("field", function() {
  $scope.fieldCopy = $scope.field;
});

不要这样做,这听起来像是在试图将DOM逻辑(例如,如果用户与DOM元素交互)引入控制器

如果您阅读ngChange指令的源代码,您会发现它需要一个ngModel,作为视图和控制器之间的桥梁

我建议您创建一个模型副本,并在视图中使用ngModel+ngChange将该副本用于数据绑定,然后您可以$watch该副本并执行任何您想要的操作

$scope.field = "hello"; //the field you care
$scope.fieldCopy = $scope.field; //use 'fieldCopy' for databinding
在html代码中,您可以使用多种方式更改模型fieldCopy

<input ngModel="fieldCopy" name='foo' />
<input ngModel="fieldCopy" name='foo2' />
如果要使fieldCopy与field保持同步,请添加另一个手表:

$scope.$watch("field", function() {
  $scope.fieldCopy = $scope.field;
});

Jeremy您只描述了Angular中的指令。每次需要接触DOM时始终使用指令是最佳实践。这种逻辑不应该存在于控制器甚至服务中

指令是一个非常棘手的问题,但是有大量的文档


访问docs.angularjs.org/directives

Jeremy您只需描述Angular中称为指令的内容。每次需要触摸DOM时始终使用指令是最佳实践。此逻辑不应存在于控制器甚至服务中

指令是一个非常棘手的问题,但是有大量的文档


访问docs.angularjs.org/directives

Hmm,关闭,但如果$scope.field从另一个回调更改,则$scope.fieldCopy将不同步。您可以在该字段中添加一个手表并同步该字段副本。在这种情况下,只有当相关字段具有可靠的angular.equals时,才可能进行此操作。否则,无法阻止infinite$digest loop.Hmm,关闭,但是如果$scope.field从另一个回调更改,那么$scope.fieldCopy将不同步。在这种情况下,您可以向该字段添加一个手表并同步该字段副本。只有当相关字段有可靠的angular.equals时,这才可能。否则,将无法阻止无限的$digest循环。My cascading update dependency graph中有循环,而$watch的不确定性使得它不可能在所有情况下正确遍历该图,例如,确保每个节点在场景A中只处理一次,但在场景B中允许它处理两次。此外,旧的!=新的检查不足以终止无限的$digest除了最琐碎的用例外,在任何情况下都可以循环。如果由我决定,我只想使用ngChange并完成它,但这不由我决定,我正在寻找解决办法。将此作为答案-因为我开始认为我的想法不是一个好主意。谢谢你的解决建议。我会研究它。我的级联更新依赖于ncy图中包含循环,$watch的非确定性性质使得在所有情况下都无法正确遍历该图,例如,确保场景A中的每个节点只处理一次,但在场景B中允许它处理两次。此外,旧的!=新的检查不足以终止除m之外的任何场景中的无限$digest循环ost琐碎的用例。如果由我决定的话,我只会使用ngChange并完成它