【问题标题】:Inheritance and nested views in AngularJSAngularJS 中的继承和嵌套视图
【发布时间】:2013-09-01 00:15:38
【问题描述】:

我正在尝试在 angularjs 中设置一些嵌套视图。我一直在使用ui-router 库来执行此操作,这在大多数情况下都非常有用。问题是每个视图都有一个单独的控制器,它们之间没有真正的继承。如果我想从子控制器修改父控制器中的某些内容,我必须使用 $scope.$parent 。这有点痛苦,如果有多个继承级别,并且您必须记住您正在访问的变量位于哪个级别,它可能会变得更糟。此外,如果您忘记在子控制器中使用 $parent 并尝试修改父变量之一,Angular 将创建该变量的新实例,这可能会导致一些难以追踪的错误。

理想情况下,我只能使用原型继承。这也可以很好地映射到 Typescript 或 Coffeescript 中的类。我想到的一种方法是摆脱所有的父控制器,只让子控制器继承原型(超类)的任何通用功能。然后你只需要把控制器扔到 $rootScope 上,这样父视图就可以访问它。

谁能想到这个解决方案或更好的解决方案有什么问题?我最好只使用 $parent 并让 Angular 处理“继承”。

谢谢

【问题讨论】:

    标签: javascript inheritance angularjs typescript angular-ui-router


    【解决方案1】:

    如果您稍微修改源代码,您应该能够启用原型继承。

    打开文件 ./ui-router/src/viewDirective.js ,您应该会在顶部附近找到它:

    var directive = {
        restrict: 'ECA',
        terminal: true,
        transclude: true,
        ...
    

    添加另一行,如下所示:

    var directive = {
        restrict: 'ECA',
        terminal: true,
        transclude: true,
        scope: true,
        ...
    

    这应该启用继承。 我找不到一个好的直接来源,但this you tube playlist 充满了各种角度的优点。

    【讨论】:

    • 这很有效,尽管它在“控制器为”语法中效果不佳。例如,如果在我的模块配置中我有“控制器:“myChildCtrl as ctrl”,那么我无法通过“this”访问父范围。例如这不起作用'this.someParentVariable = 3'。然而,这将工作 '$scope.ctrl.someParentVariable = 3'。
    • 继承的工作原理有些混乱。 $scopes 是控制器使用的对象,它们相互继承——而不是控制器。当控制器放置在 DOM 元素上时,该元素上的 $scope 通常继承自祖先 DOM 元素上的 $scopes,而控制器与此没有任何直接关系。据我所知,使用“controller as ctrl”语法实际上是在当前范围内引用了控制器。这与您在控制器的构造函数中引用为“this”的对象相同。
    • “controller as”语法被一些人(包括我在内)认为是有害的。如果您希望控制器实例具有通用功能或实例变量,则可以如上所述进行原型继承,但两个实例仍然不会共享相同的范围。您应该使用服务在控制器实例之间共享数据。
    【解决方案2】:

    正如 John 指出的,$scope 对象相互继承,但实际的控制器却没有。所以我决定设置它,以便控制器相互继承。为此,我有一个看起来像这样的根控制器:

    function rootCtrl($scope) {
        $scope.ctrl={};
        $scope.ctrl.scope = $scope;
    }
    

    然后在我嵌套最深的子控制器中,我有这样的东西

    function myCtrl($scope, $dependency1, $dependency2) {
        myCtrlImpl.apply($scope.ctrl, [$http, $dependency1, $dependency2]);
    }
    
    function myCtrlImpl($dependency1, $dependency2) {
        this.someVariableThatIsAccessableEverywhere = ":)";
    
        //If I want to access scope from here I can just do something like
        //this.scope.$watch...
    }
    

    现在,如果我想将任何功能从 myCtrlImpl 移到基本原型中,我可以使用标准原型继承。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-30
      • 2013-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多