继承 w/ Angular 的 'Controller As' 与 $scope

Inheritance w/ Angular's 'Controller As' vs. $scope

tl:dr;

我想考虑 'controller as' 方法来简化我的继承过程,但是我发现依赖注入和在指令中使用存在一些缺陷。


前言

过去 6 个月我一直在开发一个相当大的 Angular 应用程序。我来自更面向对象的语言背景,但我觉得我已经很好地适应了 javaScript 和 Angular.

的一些古怪之处

对于这种复杂性的应用程序,我认为它需要 伟大的 架构解决方案。我选择了 baseController 类,UI 控制器可以使用下面的当前方法继承。

当前方法

当前全部UIviews/components/etc。正在利用 $scope 作为视图模型方法,又名。 经典方法。我这样实现了控制器继承:

NxBaseUi控制器
var NxBaseUiController = function($scope)
{
    $scope.isLoggedIn = function(){}
    $scope.doSomethingElse = function(){}
}

这是一个子类基控制器,它是继承

NxBaseListUiController
var NxBaseListUiController = function($scope)
{
    var NxBaseUiController = require( './NxBaseUiController' )
    NxBaseUiController.apply( this, arguments )
    NxBaseListUiController .prototype = Object.create( NxBaseUiController.prototype );

    $scope.query = require( './QueryModel' ).new()
}

这种方法的疯狂之处在于我必须保持 2 个系列的继承,同时牢记在视图层次结构中发生的现有 NG 范围继承。您可以在下面的 UML 图中看到这一点:

源 - http://i.imgur.com/LNBhiVA.png

到目前为止一切正常,但是转到应用程序的新部分,我想开始查看 'Controller As' 语法,看看是否可以对上述方法进行任何简化。

问题

在我见过的关于 'controller as' 方法的所有示例中,附加的任何方法都 不是 在原型上定义的,而是实际的构造函数,如下所示:

function SomeController($scope)
{
   this.foo = function(){}; 
}

您不想在原型上定义控制器方法的原因是什么?

我认为附加到原型是有问题的唯一原因是您丢失了对注入的依赖项的引用。


我意识到我是从一种非常面向对象的方法来解决这个问题的,但是对于这种规模的应用程序,能够利用继承等开发模式似乎是解决代码重复的必要条件。

我是不是完全倒退了?是否有任何经过验证的方法可以在控制器中实现某种继承的外观,而不需要一些靠不住的黑客来使用 $scope?

只要您可以接受失去拥有实际私人数据的能力与拥有传统私人数据的能力,就没有理由不使用原型。

我用代码解释一下:

function MyClass($http){
  var privateData = 123,
      $this = this;

  $this.getAnswer = function(){
     return privateData;
  };
}

MyClass.$inject = ['$http'];

在该示例中,一旦实例化了 class,您实际上无法更改 privateData

function MyClass($http){
  this._privateData = 123;
  this.$http = $http;
}

MyClass.$inject = ['$http']; 

MyClass.prototype = {
   getAnswer: function(){
      return this._privateData;
   },
   callHome: function(){
      var _this = this;

      _this.$http.get('/api/stuff')
         .success(function(data){
            _this.stuff = data;
         });
   }
};

在那个例子中,我只是使用一个约定,在我的属性前加上下划线 (_) 来表示它们应该被视为私有的。

但是,除非您正在构建可重复使用的库,否则这可能不是什么大问题。

请注意,使用 ES6 时,其中一些变得更简单,所以如果我是你,我会研究 6to5 or TypeScript 之类的东西。编写这样的代码可能会更好地结合您的 OO 背景:

//100% valid ES6
class MyClass extends BaseClass {
   constructor(something){
      super(something, 'foo');
   }

   someMethod(){
      return this.foo;
   }
}