我刚刚看到一个关于Angular js控制器继承的示例代码来自此网址http://viralpatel.net/blogs/angularjs-controller-tutorial/
这是代码,我只是不理解一部分。
<div ng-controller="BMWController">
My name is {{ name }} and I am a {{ type }}
<button ng-click="clickme()">Click Me</button>
</div>
<script>
function CarController($scope) {
$scope.name = 'Car';
$scope.type = 'Car';
$scope.clickme = function() {
alert('This is parent controller "CarController" calling');
}
}
function BMWController($scope, $injector) {
$injector.invoke(CarController, this, {$scope: $scope});
$scope.name = 'BMW';
}
</script>
1)我只是不理解这行代码$injector.invoke(CarController, this, {$scope: $scope});
2)哪个$ scope是 BMWController 范围,哪个$ scope是 CarController 范围?
3)左边有两个范围{$ scope:$ scope},右边有一个范围,其中一个与 BMWController&amp; amp; CarController范围?
4)为什么在调用函数中使用此关键字?
5)请帮助我理解这一行 $ injector.invoke(CarController,this,{$ scope:$ scope}); 尽可能多的简单解释
感谢
答案 0 :(得分:2)
1)你运行一个函数(CarController
)并提供参数($scope
)
2)您将当前范围(BMWController
)传递给CarController
,因此它们共享范围。
3)行{$scope: $scope}
使用键$scope
创建一个对象,并使用对象$scope
对其进行初始化。尝试查看第一个$scope
,就像任何其他对象键一样,name
将在{name: 'Mou'}
4)调用只运行具有给定参数的函数:$injector documentation
您将函数传递给调用函数,但该函数没有上下文。你需要告诉它你想要运行它的位置。因此通过传递它是BMWController,它运行在BMWController内部
答案 1 :(得分:2)
行$injector.invoke(CarController, this, {$scope: $scope});
调用函数CarController
并将BMWController
的{{1}}作为参数传递。
你可以看到它:
$scope
您还可以传递其他参数,例如:
function CarController($scope) {
// ...
}
function BMWController($scope, $injector) {
CarController($scope);
$scope.name = 'BMW';
}
因此,不是直接调用控制器函数,而是使用依赖注入器来调用它。依赖注入是一种设计模式,具有多个优点,如here所述。
修改强>
function CarController($scope, foo) {
// ...
}
function BMWController($scope, $injector) {
// ...
$injector.invoke(CarController, this, {$scope: $scope, foo: bar});
}
调用函数this
的可选参数,用于将当前上下文:$injector.invoke(fn, [self], [locals]);
传递给调用的控制器函数BMWController
。
在此示例中,我们在CarController
上下文中定义this.foo
,然后我们可以在BMWController
上下文中访问foo
。
CarController
答案 2 :(得分:1)
阅读Doc后,我认为这些行意味着你:
$injector.invoke(CarController...
:调用CarController函数; ... , this ...
:对调用者的引用; ...{$scope: $scope})
:CarController具有$ scope的依赖关系,因此这一行意味着您将BmwController $范围注入CarController。除此之外,我真的认为控制器继承是一种非常糟糕的做法。如果您需要在两个控制器之间共享某些逻辑,则应使用Angular Services。它们是在您的应用程序的所有生命周期中存在的单例,用于存储逻辑或数据,更重要的是,使您的控制器更加美观。
看一下这个例子:
https://jsfiddle.net/relferreira/2b5amcya/
<强> HTML:强>
<div data-ng-app="app">
<div data-ng-controller="MainController as mainVm">
{{mainVm.name}}
</div>
<div data-ng-controller="DetailController as detailVm">
{{detailVm.name}}
{{detailVm.other}}
</div>
</div>
<强> JS:强>
angular.module('app', []);
angular.module('app')
.controller('MainController', mainController);
mainController.$inject = ['UserService'];
function mainController(UserService){
var vm = this;
vm.name = UserService.getName();
}
angular.module('app')
.controller('DetailController', detailController);
detailController.$inject = ['UserService'];
function detailController(UserService){
var vm = this;
vm.name = UserService.getName();
vm.other = 'test';
}
angular.module('app')
.factory('UserService', userService);
function userService(){
var name = 'Renan';
return{
getName: getName
}
function getName(){
return name;
}
}
修改强>:
查看AngularJs源代码,我们可以找到调用方法:
function invoke(fn, self, locals, serviceName) {
if (typeof locals === 'string') {
serviceName = locals;
locals = null;
}
var args = injectionArgs(fn, locals, serviceName);
if (isArray(fn)) {
fn = fn[fn.length - 1];
}
if (!isClass(fn)) {
// http://jsperf.com/angularjs-invoke-apply-vs-switch
// #5388
return fn.apply(self, args);
} else {
args.unshift(null);
return new (Function.prototype.bind.apply(fn, args))();
}
}
如您所见,它正在使用Function.prototype.apply()方法。正如Alex所说,这个方法需要一个上下文,它最常用于继承和/或覆盖方法。看看这个答案:
https://stackoverflow.com/a/560952/1108979
它使用call
方法,类似于apply
。