在AngularJS中有没有一种方法可以在不使用$watch的情况下对模型变化做出反应?

Is there a way in AngularJS to react on model changes without using $watch?

本文关键字:情况下 watch 模型 变化 有没有 AngularJS 方法 一种      更新时间:2023-09-26

我正在AngularJS中实现一个简单的旋转控件,我想对用户输入和+/-按钮的更改做出反应。这是我的HTML:

<input type='button' ng-click="MyProperty = MyProperty - 1" value="-">
<input type='text' ng-model="MyProperty" ng-change="log('changed from ngChange')">
<input type='button' ng-click="MyProperty = MyProperty + 1" value="+">

但这将只跟踪'用户更改',因为ngChange只支持用户交互更新,根据文档

现在我在看Frederik推荐的$scope.$watch:

$scope.$watch('MyProperty', function() {
  $scope.log('changed from $watch');
});

参见活塞演示

但这似乎不够正确。

  1. 首先它不是声明性的,你必须搜索MyTestProperty代码来找到这个绑定。
  2. 如果你想把$scope.log放在一个单独的模型中,你必须要么注入$scope,要么在控制器中做绑定。据我所知,这两种方法都不被认为是最佳做法。
有些人认为$watch总的来说是一件坏事,原因有很多。但这里建议的解决方案(即在ngClick中直接调用log)对我来说并没有太大的不同。基本上,你必须手动跟踪所有的更改,如果有新的actor出现,你必须复制你的逻辑。

所以的问题将是:有没有一种方法,可以让你自动跟踪模型更新没有$watch?如果有这样的方法来实现你自己的指令,这个想法有多糟糕?

有几种方法可以做到这一点,但最优雅的方法是要求输入的ngModel,然后使用它来查看/操作值。

这里是你的更新砰砰作响。

.directive('outputIt', function() {
    return {
      restrict: 'A',
      scope: {
        outputIt: '&'
      },
      require: '?ngModel',
      link: function(scope, element, attrs, ngModelCtrl) {
        ngModelCtrl.$parsers.push(function(val) {
          //console.log("the model was changed by input")
          scope.outputIt()(val);
        });
        ngModelCtrl.$formatters.push(function(viewValue) {
          //console.log("the model was changed from outside.");
          scope.outputIt()(viewValue);
          return viewValue;
        });
      }
    }
  })


想了解更多,这里有一篇很酷的文章:为

祝你好运!

您研究过ES5的方式吗?它本质上是javascript的原生$watch功能。不同之处在于,set/get函数被封装在属性中,而$watch可以应用于外部的任何地方。

var MyCtrl = function(){
  this._selectedItem = null;
};
Object.defineProperty(MyCtrl.prototype, "selectedItem", {
    get: function () {
        return this._selectedItem;
    },
    set: function (newValue) {
        this._selectedItem = newValue;
        //Call method on update
        this.onSelectedItemChange(this._selectedItem);
    },
    enumerable: true,
    configurable: true
});

当然可以使用:

<input type="number" />

这将创建一个spinner =)