AngularJS:如何从控制器中的模型数据中正确设置服务属性?

时间:2014-01-18 02:10:15

标签: javascript angularjs angularjs-scope angularjs-service angularjs-controller

我已经设置了一个服务来在多个控制器之间共享一些数据/状态。在一个控制器中,我通过保存功能使用范围数据更新一些服务属性。然后,通过为服务分配范围值,将该数据用于其他控制器。问题是,根据第一个控制器分配给服务的数据类型,它们的行为是不同的。如果模型数据是原始值,则只有在运行保存功能时才会更新服务的属性。但是,如果模型数据是一个对象,它将在模型数据更改时继续更新服务。我正在寻求实现“保存”功能,所以这不是我想要的。

所以我试图理解不同的行为:原始与对象以及为什么对象立即更新,以及与对象一起实现保存功能的正确方法。我知道你可以使用事件,我可以在$ rootScope上使用$ broadcast和event,并在第二个控制器上使用该事件将服务属性分配给范围var,但我喜欢将服务分配给范围的简单性第二个控制器,如果可能,我想使用该方法。

这是一个简化的例子。

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

myApp.service('myService', function () {
    this.text = '';
    this.objText = {};

    this.setText = function (text) {
        this.text = text;
    };

    this.setObjText = function (obj) {
        this.objText = obj;
    };
});

myApp.controller('InputCtrl', ['$scope', 'myService', function ($scope, myService) {
    $scope.textObj = {};
    $scope.saveText = function (text) {
        myService.setText(text);
    }
    $scope.saveObj = function (obj) {
        myService.setObjText(obj);
    }
}]);

myApp.controller('OutputCtrl', ['$scope', 'myService', function ($scope, myService) {
    $scope.myService = myService;
}]);

在视图中(部分):

<div ng-controller="OutputCtrl">
    <strong>Text:</strong> {{ myService.text }}<br>
    <strong>Obj Text:</strong> {{ myService.objText }
</div>

完整的小提琴:http://jsfiddle.net/anpsince83/uRH93/2/

1 个答案:

答案 0 :(得分:3)

这与Angular无关。它很简单,与JavaScript有关。

在您的小提琴的HTML中(数字仅供参考):

(1)<input type="text" ng-model="text1">
(2)<button ng-click="saveText(text1)">Save Text</button>
   ...
(3)<input type="text" ng-model="textObj.text1">
(4)<input type="text" ng-model="textObj.text2">
(5)<button ng-click="saveObj(textObj)">Save Object Text</button>

'字符串'案例(原语):

Line(1)在InputCtrl的作用域(以下称为inScope)中创建一个名为text1的字符串变量,并将其绑定到输入字段的值。每当输入字段的值发生变化时,inScope.text1的值也会发生变化 单击按钮(第(2)行)后,myService的text变量将设置为 inScope.text1的值。因为'string'是一个原语,所以它是按值传递的,这意味着myService.textinScope.text1 引用相同的对象 - 它们只是“碰巧”具有相同的对象调用saveText()方法后的值。 inScope.text1更改后(例如,用户在输入字段中输入内容),myService.text对此一无所知。这种情况相当于:

var a = 'value1';
var b = a;
// Now: a === 'value1', b === 'value1'

a = 'value2';
// Now: a === 'value2', b === 'value1'

'对象'案例(对象):

第(3)行和第(4)行在inScope的text1变量引用的(最初为空)对象中创建了两个属性(text2textObj)。每当输入字段的值发生变化时,inScope.textObj引用的对象的相应属性的值也会发生变化。
单击按钮(第(5)行)时,myService的object变量将设置为引用inScope.textObj相同的对象。您注意到我使用术语引用而不是。因为'object'不是原始的,所以它是通过引用传递的,这意味着myService.objectinScope.textObj引用了相同的对象(在saveObj()方法之后更改第(2)和(3)行中定义的输入字段的值会影响inScope.textObj引用的对象的属性(也由myService.object引用)。这种情况相当于:

var a = { key: 'value1' };   // Creates new object, say {obj1}
var b = a;                   // Now b references {obj1} as well
// Now: a.key === 'value1', b.key === 'value1'

a.key = 'value2';   // Changes {obj1}'s key's value
                    // but {obj1} is also referenced by b, so...
// Now: a.key === 'value2', b.key === 'value2'

// This does not happen in your code, so you never lose reference to
// the same object from both `myService.object` and `inScope.textObj`
a = { key: 'value3' };   // Creates new object, say {obj2}
                         // but b still references {obj1}, not {obj2}, so...
// Now: a.key === 'value3', b.key = 'value2'

关于JS原语与对象的

More info