如何将对象属性(也是对象)的指针/引用添加到角度$ scope?
请考虑以下代码:
videosModule.factory('VideoManager', ['YtVideos', function(YtVideos){
return {
videos: [{}, {}, {}],
currentVideo: {},
counter: 0,
setCurrentVideo: function(){
this.currentVideo = this.videos[this.counter];
}
};
}]);
控制器:
videosModule.controller('SelectVideoCtrl', ['VideoManager', '$scope', function(VideoManager, $scope){
$scope.currentVideo = VideoManager.currentVideo;
$scope.videomanager = VideoManager;
}]);
现在我希望控制器中的第一行指向属性currentVideo,这样当服务中更改它时,它将更新为$ scope。
这不起作用,但是当我引用整个服务(第二行)并使用{{videomanager.currentVideo}}时,它确实有效。
有人可以解释一下吗? 感谢。
答案 0 :(得分:1)
$scope.currentVideo = VideoManager.currentVideo;
是对你价值的影响。这意味着它永远不会改变。如果进行此更改,则使用第二种语法:$scope.videomanager = VideoManager;
,它与所有工厂类似。然后你可以找到currentVideo
。
但是如果你想要第一种语法(并避免使用墙工厂对象),你可以使用一个函数。一个吸气剂会很好:
videosModule.factory('VideoManager', ['YtVideos', function(YtVideos){
return {
videos: [{}, {}, {}],
currentVideo: {},
counter: 0,
setCurrentVideo: function(){
this.currentVideo = this.videos[this.counter];
},
getCurrentVideo : function(){
return this.currentVideo;
}
};
}]);
然后你的控制器必须链接这个吸气剂。
videosModule.controller('SelectVideoCtrl', ['VideoManager', '$scope', function(VideoManager, $scope){
$scope.currentVideo = VideoManager.getCurrentVideo;
$scope.videomanager = VideoManager;
}]);
请注意,控制器中没有()
。如果要刷新值,则必须将它们放在yur DOM中。这里只是功能链接。在您的HTML上,它将是这样的:
{{currentVideo()}}
答案 1 :(得分:0)
在您的控制器中,您正在引用VideoManager.currentVideo到$ scope.currentVideo
$scope.currentVideo = VideoManager.currentVideo;
哪个没问题,直到你不改变VideoManager.currentVideo的引用。当您在服务中更改currentVideo引用时,VideoManger.currentVideo将指向新引用但您的$ scope.currentVideo仍指向旧引用。
如果您使用对象并修改其属性,但是为了访问该属性您正在使用该对象,那么它将正常工作。您的以下陈述也是如此
$scope.videomanager = VideoManager;
在此,$ scope.videomanager指向您的服务VideoManager。你永远不会改变VideoManagaer的参考。所以$ scope.videoManger将始终指向整个应用程序中的相同引用。如果更改了VideoManager的任何属性,那么它将反映您的控制器,因为您正在使用服务对象访问它。
答案 2 :(得分:0)
所以,在angularjs中,Service只是单身,而且它们是懒惰的实例化。
Angular服务是:
Lazily实例化 - Angular仅在实例化时实例化服务 应用程序组件取决于它。
单身 - 每个组件 依赖于服务获取对单个实例的引用 由服务工厂生成。
您可以在没有任何getter功能的情况下执行此操作,只需将服务包装到 CGFloat h = [self getCollectionViewHeight];
NSDictionary *metrics = @{@"WPTableViewWidth" : @(self.frame.size.width/3),
@"verticalMargin" : @(verticalMargin),
@"intranetHeight" :@(h),
@"imageGalleryHeight" :@([_imageGallery GetHeight]),
@"nonimageGalleryHeight" :@([_nonimageGallery GetHeight]),
@"commentHeight" :@(0)};
。
在您的示例中,$scope
只是指您视频的名称,只是一个字符串,而不是一个对象,不是您的服务。
但是,如果你执行$scope.currentVideo = VideoManager.currentVideo;
,则会将服务包装到$scope.videomanager = VideoManager;
。然后,当您更新服务中的值时,范围中的数据将会更改,因为$scope
将是整个服务,并且数据会在您的范围内发生变化,因为您的{ {1}}指向您的服务。
所以你可以这样做:
<强>控制器强>
$scope.videomanager
<强> HTML 强>
$scope
答案 3 :(得分:0)
Angular仅跟踪在AngularJS上下文中完成的模型更改(即更改模型的代码包含在$ apply()中)。 Angular的内置指令和控制器已经这样做,因此您所做的任何模型更改都会反映在视图中。但是,如果您更改Angular上下文之外的任何模型(在本例中为service),则需要通过手动调用$ apply()来通知Angular更改。这就像告诉Angular您正在更改某些模型,它应该激活观察者,以便您的更改正确传播。 当你使用
$scope.currentVideo = VideoManager.currentVideo
Angular不跟踪VideoManager,因此VideoManager.setCurrentVideo方法内的更改不会触发模型更改。 但是当你使用
时$scope.videomanager = VideoManager;
Angular正在跟踪VideoManager,因此方法VideoManager.setCurrentVideo正在$ apply()中执行,该方法内置在控制器中。
例如,下面的代码可以使用,但我不推荐它。
videosModule.factory('VideoManager', ['YtVideos', '$rootScope', function(YtVideos, $rootScope){
return {
videos: [{}, {}, {}],
currentVideo: {},
counter: 0,
setCurrentVideo: function(){
this.currentVideo = this.videos[this.counter];
$rootScope.$broadcast('scope.changed');
}
};
}]);
videosModule.controller('SelectVideoCtrl', ['VideoManager', '$scope', function(VideoManager, $scope){
$scope.$on('scope.changed', function () {
if ($scope.apply) $scope.apply();
});
$scope.currentVideo = VideoManager.currentVideo;
}]);