Angularjs 什么';s将服务数据绑定到角度视图的最佳实践(1.3)

Angularjs 什么';s将服务数据绑定到角度视图的最佳实践(1.3),angularjs,Angularjs,我是Angular的新手,但在编码方面有相当多的经验,并且在视图中获取数据绑定“正确”时遇到一些困难 我的方法大致如下: 将所有逻辑排除在控制器之外,并将其封装在服务中(请参阅) 根据使用ControllerAs语法 我感到困惑的是,没有明确的$scope对象会混淆MVC理念中的模型。这篇博文中对此有一个解释,但我没有看到任何关于这件事的真正结论 角度文档声明该模型是数据的“单真实点”。也许我读了很多(这只是V和C之间值的“真值”吗?),但这表明,如果使用ControllerAs语法,控制器

我是Angular的新手,但在编码方面有相当多的经验,并且在视图中获取数据绑定“正确”时遇到一些困难

我的方法大致如下:

  • 将所有逻辑排除在控制器之外,并将其封装在服务中(请参阅)
  • 根据使用
    ControllerAs
    语法
我感到困惑的是,没有明确的
$scope
对象会混淆MVC理念中的模型。这篇博文中对此有一个解释,但我没有看到任何关于这件事的真正结论

角度文档声明该模型是数据的“单真实点”。也许我读了很多(这只是V和C之间值的“真值”吗?),但这表明,如果使用
ControllerAs
语法,控制器属性就是模型和“单点真值”

如果这是给定的,并且您希望将所有逻辑抽象到服务中,那么在我看来,您无法摆脱两个非常丑陋的备选方案之一,即保持控制器属性与服务值同步:

  • 向视图公开服务。i、 e.
    myController.data=service.data
    。这是可行的,但非常糟糕,因为所有的服务数据都暴露在视图中,而这些精简控制器的作用不就是充当视图的门面吗?或者从另一个角度来看,该服务现在已经成为一个事实上的“胖”控制器,充满了业务逻辑
  • 仅公开您希望视图访问的服务中的元素,但在每个元素上放置
    $watch
    表达式。这并不理想,因为
    • 您向控制器添加了大量样板文件
    • 您在代码中显著增加了watch表达式的数量(angular在template controller链接上放置了一个watch,并为中的每个变量添加了控制器服务链接)
  • 在Angular 1.3中,这真的是唯一的方法吗?还是我错过了一些(更优雅的)东西?


    编辑:根据答案和一些额外的调查,我收集了我对本文中问题的想法。它包括3种不进行服务绑定的方法(IMHO)和两种可能更接近“正确”方法的方法。

    服务返回模型。控制器与服务交互以填充视图模型($scope)。视图与视图模型交互以渲染视图

    要保持数据同步,您有几个可用选项

    选项1:引入一个工厂或服务,其任务是跟踪实例,比如缓存服务。任何需要绑定到视图的实例的控制器都可以从服务请求该实例。这是干净的-不需要显式的监视表达式或非特定的模型绑定

    这里有一个例子。假设要跨多个控制器绑定到用户对象

    创建用户服务

    app.factory('UserService', function() {
        return {
            getUserById: function(id) {
               ...
               return user;
            }
        }
    });
    
    app.factory('CachedUserService', function(UserService) {
         var cache = [];
         return {
             getUserById: function(id) {
                 if (!cache[id])
                     cache[id] = UserService.getUserById(id);                    
                 return cache[id];                 
             }
         }
    });
    
    创建缓存用户服务

    app.factory('UserService', function() {
        return {
            getUserById: function(id) {
               ...
               return user;
            }
        }
    });
    
    app.factory('CachedUserService', function(UserService) {
         var cache = [];
         return {
             getUserById: function(id) {
                 if (!cache[id])
                     cache[id] = UserService.getUserById(id);                    
                 return cache[id];                 
             }
         }
    });
    
    在这里,我们利用单例(所有工厂和服务都是单例),并依赖缓存服务来保留模型引用。后一点对于确保视图更改与模型更改同步至关重要

    在任何需要缓存用户服务的控制器中使用该服务:

    app.controller('ctrl', function($scope, CachedUserService) {
         $scope.user = CachedUserService.getUserById(...);
    });
    
    选项2:只需在$scope链(即$rootScope)的更高位置存储您希望保持同步的模型


    由于原型作用域继承,任何子作用域都能够绑定到作用域链更高的模型。但是,当您在$scope上分配或覆盖模型时,请小心-您可能会无意中破坏模型绑定。要保留引用,请使用
    angular。请复制

    谢谢您的回答。这就是我一直在做的事情。但我的挫折在于我如何解释Angular docs关于集合上的
    $watch
    es是如何工作的。我已经更新了plunkr以反映这一点——这里提供的简单工厂是缓存服务的代理。对于您描述的用例,我不会设置$watchs。你说得对-有更好的方法确保数据与视图同步(上面列出了两个选项)$手表应该为自定义指令中的链接函数保留,在自定义指令中可能需要对DOM进行操作