【问题标题】:How to trace source of $watch model updates in AngularJS?如何在 AngularJS 中跟踪 $watch 模型更新的来源?
【发布时间】:2013-12-28 00:05:25
【问题描述】:

在我的多用户 AngularJS 应用程序中,我的作用域上有一个模型对象。这个模型可以通过用户输入和服务器更新来操作。

我有一个 $watch 观察者来跟踪模型并更新 UI。是否可以从我的 $watch 函数中确定我的模型更新的来源/原因?如果没有该检查,我会遇到反馈循环问题(例如 UI→Server→UI)。

更新:一些代码

控制器:

$scope.elementProperties = { left: 0 };

$scope.$watch('elementProperties.left', function(newVal, oldVal) { changeSelectedElementProperty('left', newVal, oldVal); } );

指令:

angular.module('myapp.ui-editor').directive('myappPropertiesPanel', function () {
    return {
        templateUrl: 'views/ui-editor/myappPropertiesPanel.html',
        restrict: 'A',
        scope: { elementProperties: '=' },

        link: function postLink (scope, element, attrs) {
            scope.$watch('elementProperties.left', function(newVal, oldVal) { console.log('PropertiesPanel change left', newVal, oldVal); } );
        }
    };
});

【问题讨论】:

  • 当数据来自服务器/用户界面时,你不能设置一些标志吗?
  • 你能举个例子吗?标记是有意义的,或者使用广播事件可能会有所帮助
  • 或者在elementProperties上设置一个新属性,包含最后的变化源
  • 但是我如何检测更改是否发生在 UI 中(例如 myappPropertiesPanel 指令)? scope.$watch 似乎按照它们发出的顺序触发,因此控制器 $watch 语句在指令之前触发。

标签: javascript angularjs angularjs-scope


【解决方案1】:

实现此目的的一种方法是使用事件而不是 $watch

working plunker here

在我的 plunker 中,我输入了一个 $interval,它将通过每隔几秒更改一次值来模拟 Web 服务调用。

这是你可以做的。

在您的 http 调用的 then 处理程序中,在将从 Web 服务检索到的新值设置为模型之前,发布一个事件,其有效负载包含旧值和新值,如下所示:

$http.get('url goes here')
 .then(function (response) {
     scope.$broadcast('UPDATE_FROM_SERVER',
                      {oldValue: scope.elementProperties.left, newValue: response.data.left});
     scope.elementProperties.left = response.data.left;
  };

然后,在您的表单控件中,用户将更改值的位置,附加一个ng-click,如下所示:

ng-change="userChangeHandler(elementProperties.left, '{{elementProperties.left}}')

注意'{{elementProperties.left}}' 周围的引号。这将确保更改处理函数将获取属性的旧值。

现在,您可以像下面这样收听这些更改事件:

  $scope.$on('UPDATE_FROM_SERVER', function (event, changes) {
    // This code will be invoked when the data is changed by the server
    $scope.messages.push('Data changed by Server from ' + changes.oldValue + ' to ' + changes.newValue);
  });

  $scope.$on('UPDATE_FROM_USER', function (event, changes) {
    // This code will be invoked when the data is changed by the user
    $scope.messages.push('Data changed by User from ' + changes.oldValue + ' to ' + changes.newValue);
  });

【讨论】:

    【解决方案2】:

    “是否可以从我的 $watch 函数中确定我的模型更新的来源/原因?”

    简短的回答是否定的,不可能知道更改的来源,因为在更改时没有标记更改,而是在观察者测试 oldWatchedValue === newWatchedValue 并发现它时的以下摘要中没有通过相等性检查。因此,没有什么可以约束更改源发生更改的事实。

    【讨论】:

      【解决方案3】:

      您应该尝试解耦​​用户输入和服务器更新时发生的逻辑。

      您可以做到这一点的一种方法是让 $watch 始终更新 UI 模型。在 IU 方面,使用 ng-model 和 ng-change。例如。

      <input ng-model="myModel" ng-change="watchMyModel(myModel)">
      

      这样,当您点击 $scope.watchMyModel 函数时,您就会知道更改来自后端。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-07-31
        • 1970-01-01
        • 1970-01-01
        • 2015-03-15
        • 1970-01-01
        • 1970-01-01
        • 2014-09-05
        相关资源
        最近更新 更多