【问题标题】:how angular controller (and scope) inheritance works角度控制器(和范围)继承如何工作
【发布时间】:2015-07-26 19:08:15
【问题描述】:

我试图弄清楚控制器继承是如何工作的。我有三个控制器:

var myApp = angular.module('app', []);

myApp.controller('MainController', ['$scope', function($scope) {
    $scope.name = 'main';
    $scope.getName = function() {
        return $scope.name;
    };
}]);
myApp.controller('Child1', ['$scope', function($scope) {
    $scope.name = 'child1';
}]);
myApp.controller('Child2', ['$scope', function($scope) {
    $scope.name = 'child2';
}]);

我的看法

<div ng-app='app'>
    <div ng-controller='MainController'>
        <div ng-bind='getName()'></div>

        <div ng-controller='Child1'>
            <div ng-bind='getName()'></div>

            <div ng-controller='Child2'>
                <div ng-bind='getName()'></div>
            </div>
        </div>
    </div>
</div>

但它们都显示“主要”。我该如何解决这个问题?

这是一个小提琴http://jsfiddle.net/g3xzh4ov/3/

【问题讨论】:

    标签: angularjs


    【解决方案1】:

    Here's an example 了解如何在 Angular 中扩展控制器。

    myApp.service('baseCtrl', function () {
      this.name = 'base';
      this.getName = function() {
        return this.name;
      };
    });
    
    myApp.controller('MainController', ['baseCtrl', function (baseCtrl) {
      angular.extend(this, baseCtrl);
      this.name = 'main';
    }]);
    myApp.controller('Child1', ['baseCtrl', function (baseCtrl) {
      angular.extend(this, baseCtrl);
      this.name = 'child1';
    }]);
    myApp.controller('Child2', ['baseCtrl', function (baseCtrl) {
      angular.extend(this, baseCtrl);
      this.name = 'child2';
    }]);
    

    它必须使用controllerAs,它将$scope替换为this,特别适合这种情况。

    注意service 的用法,而不是其他 Angular 服务类型,它在底层使用了new,因此this... 语句可以直接从控制器带到单独的服务。

    有几种方法可以进行控制器继承。这里是another approach

    关于原始代码,Angular 中没有“控制器继承”。而$scope 原型继承假设

    $scope.getName = function() {
        return $scope.name;
    };
    

    从定义它的上下文返回$scope.name,在你的情况下它是MainController函数。

    【讨论】:

      【解决方案2】:

      您面临的问题实际上是基于核心 Javascript 功能。

      您知道,您所面临的困惑源于范围界定和原型继承的混合。属性被复制,但范围保持不变,阻止您访问您希望能够访问的变量。为了更好地理解这一点,也许我们可以看一个更简单的变量来代替$scope

      myApp.controller('MainController', ['$scope', function($scope) {
          var a = 1;
          $scope.getName = function() {
              console.log(a); // -> 1
              console.log(b); // Error! `Uncaught ReferenceError: b is not defined`
          };
      }]);
      myApp.controller('Child1', ['$scope', function($scope) {
          var b = 2;
      }]);
      

      很明显,MainController 不知道Child1 定义了一个名为b 的变量,所以它出错了。该变量严格超出词法范围。

      同样,如果我们将 b 重命名为 a,它不会将 MainController 中的值变为 2。这确切地说明了您正在发生的事情:您有三个名为 $scope 的东西,并且只有一个在词法范围内。

      修复它的两个选项:

      1)使用this

      $scope.getName = function() {
          return this.name;
      };
      

      this 解决方案之所以有效,是因为 Javascript 如何根据上下文确定“this”。基本上,由于它附加到给定的$scope 对象,因此该对象是一个很好的候选对象。但是 Mozilla 可以比我更好地解释这一点,因此请在此处查看他们关于该主题的页面:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

      2) 否则,您可以简单地传递$scope

      $scope.getName = function(item) {
          return item.name;
      };
      

      【讨论】:

      • 它将在他的小提琴中完美运行:jsfiddle.net/g3xzh4ov/4。无需其他更改。原型继承解决了这个问题(除非你使用bind
      【解决方案3】:

      如果您想覆盖子作用域中的名称属性,请将原始名称属性转换为对象。

      $scope.user = {};
      $scope.user.name='main';
          $scope.getName = function() {
              return $scope.user.name;
          };
      

      您应该阅读https://github.com/angular/angular.js/wiki/Understanding-Scopes 了解详细信息。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-07
        • 2016-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-07-20
        相关资源
        最近更新 更多