5

好的,让我们设置一个场景。

场景: 您有一个内容控制器。此内容可能是照片、博客文章等。现在,在此内容的 html 中,您有一个 Comment 控制器。CommentController 的工作是加载评论、允许评论提交等。然而,这个控制器的功能取决于它的父级。毕竟,如果没有父母,你在评论什么?

问题: 话虽如此,让我们引入一个问题。ContentController 需要从服务器请求信息来填充自己,其中一部分是唯一 ID。现在,还有其他方法可以解决这个问题,例如使用 url-state 作为唯一 ID,但这是我能想出的解释这个问题的最佳方法。

唯一 id 从服务器加载到 ContentController。然后它用这个 ID 和真实的内容填充它的 $scope。另一方面,CommentController 想要加载它自己的资源,但它的资源加载完全依赖于父 ContentController 加载的数据。由于两个控制器同时加载,我们需要一种方法来通知或延迟子 CommentController 的执行。否则,它将尝试从服务器请求有关不存在的唯一内容 ID 的评论。

问题: 这是一个非常基本的问题,有很多显而易见的答案。然而,我的问题是,像这样的角度是如何完成的?最适合“角度方式”的解决方案是什么。

最明显的方法是简单地拥有一个事件创建者/消费者。Angular 有多种方法来处理这个问题。例如服务、a $scope.promise = promise、resolve promise$scope.$broadcast等。不过,对我来说,这些事件设计感觉......笨拙......它也感觉紧密耦合。我希望我的 ContentController 不会被其中可能包含或可能不包含的内容所困扰。

另一种方法是$watch您想要的变量的范围,例如$scope.$watch('content.uid', function(newValue) {}). 与上述解决方案相比,这感觉更好,并且耦合度更低。虽然仍然不完美..至少对我来说。

我觉得最好的解决方案是我不知道如何实现的解决方案。我希望控制器能够..延迟子控制器,如果它(父)正在做一些异步的事情。我觉得这比一个事件要好,因为它隐含的简单。它本质上仍然是一个事件广播,但希望语法是干净的,因为只有一个“事件”。它要么不完整,要么完整。不过,我不确定如果不使用上述事件方法之一,这样的事情是否可能实现。无论如何,有没有办法实现这一点?

无论如何,自从我几周前开始学习 Angular 以来,这个问题就一直在我脑海中盘旋。任何有关该主题的见解将不胜感激。

谢谢阅读!

4

1 回答 1

7

Angular 很容易避免事件设计,或者$watch出于您所描述的目的而使用变量,特别是因为 Angular 使很多东西变得如此干净,但这并不意味着您永远不应该使用它们。

也就是说,我使用 Angular 的次数越多,我就越发现自己将数据操作从控制器中拉出,并进入公开“API”供控制器使用的服务和工厂。

例如,假设您有经典的列表视图/详细视图场景,您从列表中选择一个项目,然后在详细视图中显示其信息。

我可能有一个$resource支持列表的工厂和一个仅用于管理所选项目的服务:

app.factory('Thing', function($resource) {
  return $resource('/things/:id')
});

app.service('Selected', function() {
  this.thing = null;

  this.select = function(thing) { this.thing = thing; }
  this.clear = function(thing) { this.thing = null; }
});

通过这种方式分解,控制器只负责协调和响应视图。是的,我必须去服务,但这样$watchSelected事情或多或少是不可避免的。但是,它确实使您无需直接在数据上查看某些内容,例如uid

app.controller('List', function($scope, Thing, Selected) {
  $scope.things = Thing.query();

  // assuming something like 'ng-click="select(thing)"' in the view
  $scope.select = function(thing) {
    Selected.select(thing);
  };
});

app.controller('Detail', function($scope, Selected) {
  $scope.Selected = Selected;

  $scope.$watch('Selected.thing', function(thing) {
    $scope.thing = thing;
  });
});

然后,假设您需要为选定的“事物”加载评论,您只需Thing使用该功能增强您的工厂:

app.factory('Thing', function($resource) {
  var Thing = $resource('/things/:id');

  Thing.prototype.CommentResource = $resource('/things/:thingId/comments/:id');

  return Thing.
});

然后从您的控制器中使用该功能。

app.controller('Detail', function($scope, Selected) {
  $scope.Selected = Selected;

  $scope.$watch('Selected.thing', function(thing) {
    $scope.thing = thing;
    $scope.comments = thing.CommentResource.query({id: thing.id});
  });
});

概括

我知道在使用 Angular 时做“恢复到旧方式”的感觉时会感到恶心。

我认为诀窍是从控制器中提取除协调之外的所有内容,然后即使您必须使用一些事件或分配一堆$watches,您仍然以松散耦合的方式这样做。

这只是我的两分钱,希望它有用。

于 2013-02-21T21:59:32.777 回答