Javascript 在AngularJS服务中处理数据绑定
我试图弄清楚,当我的数据存储在服务中时,如何正确处理绑定 如果它将服务放入$scope中,然后将模板直接绑定到其中,我可以让事情正常进行,但这似乎是一个非常糟糕的主意 基本上,我希望我的视图/控制器能够轻松地更改服务中的状态,并将其反映到所有地方 我觉得我应该可以做如下的事情,但它不起作用(http://jsfiddle.net/aidankane/AtRVD/1/) HTMLJavascript 在AngularJS服务中处理数据绑定,javascript,service,binding,angularjs,Javascript,Service,Binding,Angularjs,我试图弄清楚,当我的数据存储在服务中时,如何正确处理绑定 如果它将服务放入$scope中,然后将模板直接绑定到其中,我可以让事情正常进行,但这似乎是一个非常糟糕的主意 基本上,我希望我的视图/控制器能够轻松地更改服务中的状态,并将其反映到所有地方 我觉得我应该可以做如下的事情,但它不起作用(http://jsfiddle.net/aidankane/AtRVD/1/) HTML 您可以使用$watch并传递函数绑定到服务: $scope.$watch(函数(){return myService.
您可以使用
$watch
并传递函数绑定到服务:
$scope.$watch(函数(){return myService.drawing;},函数(drawing){
//在这里处理。例如:
$scope.drawing=图纸;
});
然后在模板中使用$scope.drawing
,它们将自动更新:
{{绘图}}
我认为,更优雅的做法是使用承诺(请参见$q.deferred()
)并异步解决它们。然后,在promise函数中,您可以将数据分配给$scope
的成员。有两种方法可以从服务绑定数据:1)通过值(需要如上所述的观察者检查服务原语值的变量更改)2)通过引用(值直接链接)哪种是我首选的数据绑定方法。
我将只解释第二种可能性,因为公认的答案已经说明了如何实现观察者
以下是来自plunk的代码:
HTML
那么这是如何工作的呢
重要的是要理解,这与angular的工作原理关系不大,而与Javascript的工作原理关系很大。当变量设置为javascript(整数、字符串等)中的基元值(或传递给函数)时,变量由值设置。这意味着新变量是将其设置为与内存中的新位置相等的变量的副本。在javascript中将变量设置为等于对象(或传递给函数)时,通过引用设置变量
这是什么意思
当$scope变量由值设置,并且服务变量发生变化时,由于$scope变量只是服务变量的副本,因此服务变量不再与服务变量有任何关系,并且在服务变量发生变化时不会发生变化
当$scope变量设置为等于and对象时,它将通过引用进行赋值。这意味着当服务对象(请注意,该服务是一个对象,因为它是用new关键字实例化的,您可以在服务中用“This”引用该对象)或服务上被引用的任何对象发生更改时,引用这些对象的任何$scope变量也将更新。我看到您正在查看$scope.drawing的更改位置,但您没有更改模型,您正在更改所选项目。您不应该为所选项目的更改(可能是在指令中)添加处理程序吗?如何使用指令执行此操作?我认为ngSelect指令基本上提供了我需要的行为。我对这个问题的理解是,控制器和服务之间的移动才是问题所在——然后我现在又有点困惑:)你是对的,现在我看到了你更新的小提琴,我对你在尝试什么有了更好的了解。你没有困惑:)好的。我想这让我走上了正确的道路。因此,我创建了一个新版本--并且在两个方向上创建了观察者,以在服务之间推/拉。这是正确的做法吗?@AidanKane Yep!组件间通信是此处和邮件列表中的常见问题。到目前为止,服务是最常见的(通常是更“正确的”)解决方案。我很早就看到,它们是保存数据的正确方式。只是在服务/控制器/视图之间的协调方面有些困难。似乎通过使用该服务,我必须在控制器中添加一些样板文件来同步内容(控制器中的内容太少了,我不介意)。感谢您的及时回复,谢谢。通常会有,但这取决于上下文。例如,您可以只做
$scope.drawing=myService.drawing
,完全避免观看,但从关注点分离的角度来看,这通常是不赞成的。如果你有一个例子,我相信我们可以找到一些不那么一般、不那么冗长的东西。@mariachimike没错,但总有例外。如果你只加载一次数据就可以了,但我认为正在更改的数据不会像OP所寻找的那样自动绑定。可能是错的。
<div ng-controller="MyCtl">
<select ng-model="drawing" ng-options="d.file for d in drawings"></select>
</div>
<div ng-controller="MyOtherCtl">
{{ drawing }}
</div>
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'];
<!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>
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'
};
});