将指向/服务对象属性的引用添加到$ scope变量

时间:2015-08-03 13:22:25

标签: javascript angularjs pointers

如何将对象属性(也是对象)的指针/引用添加到角度$ 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}}时,它确实有效。

有人可以解释一下吗? 感谢。

4 个答案:

答案 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仅在实例化时实例化服务   应用程序组件取决于它。

     

单身    - 每个组件   依赖于服务获取对单个实例的引用   由服务工厂生成。

     

Services

您可以在没有任何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;
}]);