tl:dr;
I want to consider the 'controller as' approach to simplify my inheritance process however I see some pitfalls around dependency injection and use in directives.
我想把“controller”作为简化继承过程的方法,但是我看到了依赖注入和在指令中使用的一些缺陷。
preface
I've been working on a pretty big Angular application for the last 6 months. I come from a more OOP language background but feel I've adapted fairly well to some of the quirkiness of javaScript and Angular.
在过去的6个月里,我一直在研究一个相当大的角度应用。我来自于一个更加OOP的语言背景,但我觉得我已经适应了javaScript和角度的一些古怪。
With an application of this complexity, I think it necessitates great architectural solutions. I've elected to have baseController classes that UI controllers can inherit from using the current approach below.
由于这种复杂性的应用,我认为它需要伟大的架构解决方案。我已经选择了使用下面的当前方法继承UI控制器的baseController类。
current approach
All the current UI views/components/etc. are utilizing the $scope as the view model approach, aka. the classic approach. I achieved the controller inheritance like so:
所有当前的UI视图/组件/等等。将$scope用作视图模型方法,即。经典的方法。我实现了控制器继承,如下所示:
NxBaseUiControllervar NxBaseUiController = function($scope)
{
$scope.isLoggedIn = function(){}
$scope.doSomethingElse = function(){}
}
Here's a subclass base controller and it's inheritance
这是基控制器的子类,它是继承
NxBaseListUiControllervar NxBaseListUiController = function($scope)
{
var NxBaseUiController = require( './NxBaseUiController' )
NxBaseUiController.apply( this, arguments )
NxBaseListUiController .prototype = Object.create( NxBaseUiController.prototype );
$scope.query = require( './QueryModel' ).new()
}
What's crazy about this approach is that I'm having to maintain 2 series of inheritance all while keeping in mind of the existing NG scope inheritance that takes place in the view hierarchy. You can see this in the following UML diagram:
这种方法的疯狂之处在于,我必须维护两个系列的继承,同时要记住在视图层次结构中发生的NG范围继承。您可以在以下UML图中看到这一点:
src - http://i.imgur.com/LNBhiVA.png
src - http://i.imgur.com/LNBhiVA.png
This all works so far, but moving onto a new section of the app, I want to start looking at the 'Controller As' syntax to see if there can be any simplification of the above approach.
到目前为止,这一切都是可行的,但我想开始研究“Controller As”语法,看看是否可以对上述方法进行任何简化。
questions
In all the examples I've seen of the 'controller as' approach, any methods attached are not defined on the prototype but rather the actual constructor like so:
在我所见过的“controller as”方法的所有示例中,任何附加的方法都不是在原型上定义的,而是像这样的实际构造函数:
function SomeController($scope)
{
this.foo = function(){};
}
Is there a reason why you wouldn't want to define the controller methods on the prototype?
为什么您不想在原型上定义控制器方法?
The only reason I see attaching to the prototype as being problematic is you lose reference to your injected dependencies.
我认为附加到原型的唯一原因是您丢失了对注入依赖项的引用。
I realize I am coming at this from a very OO approach, however w/ an application of this size, being able to draw upon development patterns like inheritance seems necessary to solve code duplication.
我意识到我是从一个非常面向对象的方法中来的,但是这种大小的应用程序,能够利用像继承这样的开发模式来解决代码重复似乎是必要的。
Am I approaching this completely backwards? Are there any proven methods to achieving some semblance of inheritance in the controllers that doesn't require some wonky hack to work w/ the $scope?
我是在完全倒过来吗?是否有一些经过验证的方法,可以在控制器中实现某种表面上的继承,而不需要一些不稳定的技巧来工作?
1 个解决方案
#1
2
There is no reason you can't use the prototype so long as you are OK with losing the ability to have actual private data vs having conventionally private data.
没有理由你不能使用原型,只要你可以放弃拥有真正的私有数据的能力,而不是传统的私有数据。
Let me explain with code:
让我用代码解释一下:
function MyClass($http){
var privateData = 123,
$this = this;
$this.getAnswer = function(){
return privateData;
};
}
MyClass.$inject = ['$http'];
In that example you can't actually change privateData
once the class has been instantiated.
在这个示例中,一旦实例化了类,就不能实际更改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;
});
}
};
In that example I am simply using a convention of prefixing my properties with an underscore (_
) to signal that they should be treated as private.
在这个示例中,我只是使用了在属性前面加下划线(_)的约定来表示它们应该被视为私有。
Unless you are building a re-usable library however, this might not be a big deal.
但是,除非您正在构建一个可重用的库,否则这可能不是什么大问题。
Mind you some of this get's much simpler with ES6, so I would look into something like 6to5 or TypeScript if I were you. It might gel a little better with your OO background to write code like this:
请注意,使用ES6会更简单一些,所以如果我是你的话,我会研究6to5或打字稿。用OO背景编写这样的代码可能会更好一些:
//100% valid ES6
class MyClass extends BaseClass {
constructor(something){
super(something, 'foo');
}
someMethod(){
return this.foo;
}
}
#1
2
There is no reason you can't use the prototype so long as you are OK with losing the ability to have actual private data vs having conventionally private data.
没有理由你不能使用原型,只要你可以放弃拥有真正的私有数据的能力,而不是传统的私有数据。
Let me explain with code:
让我用代码解释一下:
function MyClass($http){
var privateData = 123,
$this = this;
$this.getAnswer = function(){
return privateData;
};
}
MyClass.$inject = ['$http'];
In that example you can't actually change privateData
once the class has been instantiated.
在这个示例中,一旦实例化了类,就不能实际更改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;
});
}
};
In that example I am simply using a convention of prefixing my properties with an underscore (_
) to signal that they should be treated as private.
在这个示例中,我只是使用了在属性前面加下划线(_)的约定来表示它们应该被视为私有。
Unless you are building a re-usable library however, this might not be a big deal.
但是,除非您正在构建一个可重用的库,否则这可能不是什么大问题。
Mind you some of this get's much simpler with ES6, so I would look into something like 6to5 or TypeScript if I were you. It might gel a little better with your OO background to write code like this:
请注意,使用ES6会更简单一些,所以如果我是你的话,我会研究6to5或打字稿。用OO背景编写这样的代码可能会更好一些:
//100% valid ES6
class MyClass extends BaseClass {
constructor(something){
super(something, 'foo');
}
someMethod(){
return this.foo;
}
}