服务和控制器之间的双向绑定,无需 $scope.$watch。这是一个不好的做法吗?

par*_*kLS 4 angularjs angularjs-scope

我听说,该服务不应链接到控制器中的作用域变量,因为视图可以直接访问服务。但我想将范围变量绑定到服务中存储的数据,并且我希望该变量反映服务中的所有更改。我读过很多解决方法,其中大多数都被告知使用 $scope.$watch,如果我想从控制器观看服务数据。我写了一个简单的例子,没有使用 $scope.$watch ,它的工作原理与我想要的完全一样,但我绝对不确定,我可以使用这样的东西,还是这是一个不好的做法。我学习 Angular 大约 2-3 天,非常需要你的建议:

html:

<div ng-controller="TestController">
    <p>Current value = {{ serviceData.getValue() }}</p>
    <input type="text" ng-model="newValue">
    <button ng-click="changeServiceData(newValue)">Change</button>
</div>
Run Code Online (Sandbox Code Playgroud)

模块.js

var app = angular.module('app', []);
Run Code Online (Sandbox Code Playgroud)

控制器.js

app.controller('TestController', function($scope, testService){
    $scope.serviceData = testService.getPublicData();
    $scope.changeServiceData = function(newValue){
        testService.setValue(newValue);
    }
});
Run Code Online (Sandbox Code Playgroud)

服务.js

app.factory('testService', function(){
    var value = null;
    return {
        setValue: function(newValue){
            value = newValue;
        },
        getPublicData: function(){
            return {
                getValue: function(){
                    return value;
                }
            }
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

总结一下,view 只能访问 getters。为了更新数据,我正在使用服务,我可以将其注入任何控制器中,并且服务中的所有更改都会反映在控制器和视图上。

更新: 我尝试像这样改变我的工厂:

app.factory('testService', function(){
var value = null;
return {
    setValue: function(newValue){
        value = newValue;
    },
    getValue: function(){
        return value;
    }
}
Run Code Online (Sandbox Code Playgroud)

});

并将 getter 分配给作用域:

app.controller('TestController', function($scope, testService){
    $scope.value = testService.getValue();
    $scope.changeServiceData = function(newValue){
        testService.setValue(newValue);
    }
});
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如果我使用设置器从视图中更改服务中的值,则值不会在视图中隐式更改,它不会反映实际的服务数据。也许你可以解释一下这种行为?

flo*_*bon 5

您的更新几乎是正确的,如果您决定使用包含变量的服务,则该变量应该在模块和控制器之间共享。

现在你需要做的就是使用这个 getter 和 setter:

app.controller('TestController', function($scope, testService){
  $scope.testService = testService;
  $scope.newValue    = 'initial-value';
});
Run Code Online (Sandbox Code Playgroud)

在你的 HTML 中:

<div ng-controller="TestController">
  <p>Current value = {{ testService.getValue() }}</p>
  <input type="text" ng-model="newValue">
  <button ng-click="testService.setValue(newValue)">Change</button>
</div>
Run Code Online (Sandbox Code Playgroud)

现在我们仍然将值放入范围中,因为显然您只想在单击时更新服务值,因此需要将其与服务本身去同步。

如果要将服务值直接绑定到该输入的 ngModel 中,则不能使用 getter,但必须直接使用变量:

<input ng-model="testService.value">
Run Code Online (Sandbox Code Playgroud)

或者最后一个选项是使用 ngChange 指令传播对 newValue 所做的任何更改:

<input ng-model="newValue" ng-change="testService.setValue(newValue)">
Run Code Online (Sandbox Code Playgroud)