Angular js控制器继承问题

时间:2016-04-05 14:13:24

标签: angularjs

我刚刚看到一个关于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}); 尽可能多的简单解释

感谢

3 个答案:

答案 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后,我认为这些行意味着你:

  1. $injector.invoke(CarController...:调用CarController函数;
  2. ... , this ...:对调用者的引用;
  3. ...{$scope: $scope}):CarController具有$ scope的依赖关系,因此这一行意味着您将BmwController $范围注入CarController。
  4. 除此之外,我真的认为控制器继承是一种非常糟糕的做法。如果您需要在两个控制器之间共享某些逻辑,则应使用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