服务和控制器之间的双向绑定,无需 $scope.$watch.这是一种不好的做法吗? [英] Two-way binding between service and controller without $scope.$watch. Is this a bad practice?

查看:15
本文介绍了服务和控制器之间的双向绑定,无需 $scope.$watch.这是一种不好的做法吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

html:

<p>当前值 = {{ serviceData.getValue() }}</p><input type="text" ng-model="newValue"><button ng-click="changeServiceData(newValue)">更改</button>

module.js

var app = angular.module('app', []);

controller.js

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

service.js

app.factory('testService', function(){变量值 = 空;返回 {设置值:函数(新值){价值 = 新价值;},获取公共数据:函数(){返回 {获取值:函数(){返回值;}}}}});

总而言之,视图只能访问 getter.为了更新数据,我使用了服务,我可以将其注入任何控制器,并且服务中的所有更改都会反映在控制器和视图上.

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

app.factory('testService', function(){变量值 = 空;返回 {设置值:函数(新值){价值 = 新价值;},获取值:函数(){返回值;}}

});

并将 getter 分配给作用域:

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

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

解决方案

您的更新几乎是正确的,如果您决定使用包含变量的服务,它意味着要在模块和控制器之间共享.

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

app.controller('TestController', function($scope, testService){$scope.testService = testService;$scope.newValue = '初始值';});

在你的 HTML 中:

<p>当前值 = {{ testService.getValue() }}</p><input type="text" ng-model="newValue"><button ng-click="testService.setValue(newValue)">更改</button>

现在我们仍然将 value 放入 scope 中,因为显然您只想在点击时更新服务 value,因此它需要与服务本身不同步.

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

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

I've heard, that service should not be linked to scope variable in controller because view gains direct access to service. But i want to bind my scope variable to data that stored in service, and i want that variable to reflect all changes from service. I've read a lot of workaround, and in most of them were told to use $scope.$watch, if i want to watch service data from controller. I've wrote simple example without using of $scope.$watch, which is working exactly like i want, but i'm definitely not sure, can i use something like this, or it this a bad practice. I'm learning angular for about 2-3 days, and very need your advice:

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>

module.js

var app = angular.module('app', []);

controller.js

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

service.js

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

Summarizing , view has access only to getters. To update data i'm using service, which i can inject in any controller, and all changes in service are reflected on controller, and on view.

UPDATE: I have tried to change my factory like this:

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

});

and assign getter to scope:

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

In this case, if i changing value in service from view using setter, value doesnt changing implictly in view, it doesnt reflect actual service data. Maybe you could explain such behaviour?

解决方案

Your update is almost right, if you've decided to use a service containing a variable it is meant to be shared accross modules and controllers.

What you need to do is only use this getter and setter now:

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

And in your 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>

Now we still put value into the scope because apparently you want to update the service value only on click, so it need to be desynchronized from the service itself.

If you want to bind the service value directly into the ngModel of that input, you cannot use a getter but will have to use the variable directly:

<input ng-model="testService.value">

Or one last option is to propagate any changes made to newValue using the ngChange directive:

<input ng-model="newValue" ng-change="testService.setValue(newValue)">

这篇关于服务和控制器之间的双向绑定,无需 $scope.$watch.这是一种不好的做法吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆