Angularjs 角度控制器(和范围)继承的工作原理

Angularjs 角度控制器(和范围)继承的工作原理,angularjs,Angularjs,我想弄清楚控制器继承是如何工作的。我有三个控制器: var myApp = angular.module('app', []); myApp.controller('MainController', ['$scope', function($scope) { $scope.name = 'main'; $scope.getName = function() { return $scope.name; }; }]); myApp.controller('C

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

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>

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


这里有一个难题

您所面临的问题实际上是基于核心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)使用

$scope.getName = function() {
    return this.name;
};
this
解决方案之所以有效,是因为Javascript如何根据上下文确定“this”。基本上,由于它附加到给定的
$scope
对象,因此该对象是一个很好的候选对象。但Mozilla比我能更好地解释这一点,因此请在此处查看他们关于该主题的页面:

2)否则,您只需传递
$scope

$scope.getName = function(item) {
    return item.name;
};
控制器如何在角度方向上扩展

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
替换为
,对于此类情况尤其适用

请注意使用
服务
而不是其他角度服务类型,它在引擎盖下使用
新的
,因此
此…
语句可以从控制器直接带到单独的服务

有几种方法可以实现控制器继承。这是

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

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

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

如果要覆盖子作用域中的name属性,请将原语name属性转换为object

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

您应该阅读详细信息。

这将在他的小提琴中完美发挥作用:。不需要其他更改。原型继承解决了这个问题(除非您使用
bind