20

我试图弄清楚当我的数据存储在服务中时如何正确处理绑定。

如果将服务放入 $scope 然后让模板直接绑定到其中,我可以让事情正常工作,但这似乎是一个非常糟糕的主意。

我基本上希望拥有它,以便我的视图/控制器能够轻松地更改服务中的状态并将其反映在任何地方。

感觉我应该能够执行以下操作,但它不起作用(http://jsfiddle.net/aidankane/AtRVD/1/)。

HTML

<div ng-controller="MyCtl">
    <select ng-model="drawing" ng-options="d.file for d in drawings"></select>
</div>
<div ng-controller="MyOtherCtl">
    {{ drawing }}
</div>

JS

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

myApp.factory('myService', function(){
    var me = {
        drawings: [{'file':'a'}, {'file':'b'}]
    };
    // selected drawing
    me.drawing = me.drawings[0];
    return me;
});

function MyCtl($scope, myService){
    // can do:
    // $scope.mys = myService;
    // and then in html ng-model="mys.drawing"
    // but that seems wrong

    $scope.drawings = myService.drawings;
    $scope.drawing = myService.drawing;

    // can I not do this? it doesn't seem to work anyway...
    $scope.$watch('drawing', function(drawing){
        myService.drawing = drawing;
    });
}

function MyOtherCtl($scope, myService){
    $scope.drawing = myService.drawing;
}

MyCtl.$inject = ['$scope', 'myService'];
MyOtherCtl.$inject = ['$scope', 'myService'];
4

3 回答 3

41

$watch您可以使用和传递函数绑定到服务:

$scope.$watch( function () { return myService.drawing; }, function ( drawing ) {
  // handle it here. e.g.:
  $scope.drawing = drawing;
});

然后$scope.drawing在您的模板中使用,它们将自动更新:

<div ng-controller="MyOtherCtl">
  {{ drawing }}
</div>
于 2013-01-25T17:46:59.583 回答
2

我认为,更优雅的是使用 Promise(参见 参考资料$q.deferred())并异步解决它们。然后,您可以在 promise 函数中将数据分配给$scope的成员。

于 2014-09-08T11:30:19.877 回答
2

有两种方法可以绑定来自服务的数据:1)按值(将需要如上所述的观察者来检查对服务原始值的变量更改)2)通过引用(值直接链接)这是我的首选数据绑定方法。

我只会解释第二种可能性,因为接受的答案已经显示了如何实现观察者。这个博客很好地描述了我将要解释的内容

我创建了这个 plunk 以通过引用来说明数据绑定。

这是来自 plunk 的代码:

HTML

<!DOCTYPE html>
<html ng-app="myApp">

  <head>
    <script data-require="angularjs@1.5.0" data-semver="1.5.0" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.0/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-controller="myAppCntrl">
    <h1>Hello Plunker!</h1>
    <h3>By value</h3>
    <p>{{byValue}}</p>
    <p>{{objByValue}}</p>
    <h3>By object in service reference</h3>
    <p>{{byRefence.stringPrimitive}}</p>
    <h3>By reference to service singleton</h3>
    <p>{{myservice.stringPrimitive}}</p>
    <p style="color: green">of course, you can reference an object through the service as well</p>
    <p>{{myservice.objectWithPrimitive.stringPrimitive}}</p>

    <button ng-click=update()>Update strings on service</button>
    <br />
    <button ng-click=setDefaults()>Restore Defaults</button>
  </body>

</html>

JAVASCRIPT

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

myApp.controller('myAppCntrl', function($scope, myAppService){
  $scope.myservice = myAppService;
  $scope.byValue = myAppService.stringPrimitive;
  $scope.objByValue = myAppService.objectWithPrimitive.stringPrimitive;
  $scope.byRefence = myAppService.objectWithPrimitive;

  $scope.update = function () {
    myAppService.stringPrimitive = "updated string";
    myAppService.objectWithPrimitive.stringPrimitive = "updated string here too";
  };
  $scope.setDefaults = function () {
    myAppService.stringPrimitive = 'string primitive';
    myAppService.objectWithPrimitive.stringPrimitive = 'string primitive';
  };
});

myApp.service('myAppService', function(){
  this.stringPrimitive = 'string primitive';
  this.objectWithPrimitive = {
    stringPrimitive: 'string primitive'
  };
});

那么这是如何工作的呢?

重要的是要理解这与 Angular 的工作方式无关,而与 Javascript 的工作方式有很大关系。当一个变量在 javascript(整数、字符串等)中设置为等于原始值(或传递给函数)时,var 由 value 设置。这意味着新变量是您将其设置为等于内存中新位置的变量的副本。当一个变量在 javascript 中设置为等于一个对象(或传递给一个函数)时, var 由 reference 设置

这是什么意思?

当一个 $scope var 被值设置,并且服务变量发生变化时,由于 $scope 变量只是服务变量的一个副本,所以服务变量不再与服务变量有任何关系,并且在服务时也不会改变var 可以。

当 $scope var 设置为等于和对象时,它由 Reference 分配。这意味着当服务对象(请注意,服务是一个对象,因为它是使用 new 关键字实例化的,并且您可以在服务内部使用“this”引用该对象)或服务上被引用的任何对象发生更改时,任何引用这些对象的 $scope 变量也会更新。

于 2016-03-05T23:14:43.390 回答