【问题标题】:Controller inheritance with injection带有注入的控制器继承
【发布时间】:2016-05-04 02:14:17
【问题描述】:

我很难理解用我的控制器实现继承的最佳方式。我在这里看到了一些关于这些的其他帖子,但我仍然没有得到一些东西。

这是我所拥有的: - 2 个 80% 相似的控制器。我已经有一个工厂,两者都用来获取将要显示的数据。 - 我使用控制器作为符号,带有var vm = this - 将在视图中使用的变量和函数混合在一起,因此在 vm 内部创建,而其他一些内部变量和函数则不是。 - 所以我尝试用所有这些创建一个单一的父控制器,然后使用注入来创建这两个控制器,只覆盖我需要的,但这并不像我预期的那样工作,而且我不确定这是正确的做

这是代码的简化版本。

(function() {

    angular

    .controller('ParentController', ParentController)

    ParentController.$inject = [ '$scope', '$location' ];

    function ParentController($scope, $location) {

        var vm = this; // view model

        var URL = $location.url();      

        var isDataLoaded = false;

        vm.predicate = 'order';
        vm.reverse = false;

        vm.results;     

        vm.isDataReady = isDataReady;
        vm.setOrder = setOrder;

        function isDataReady() {
            return isDataLoaded;
        }

        function setOrder(p) {
            vm.reverse = (p === vm.predicate) ? !vm.reverse : false;
            vm.predicate = p;
        }

        $scope.$on('READ.FINISHED', function() {
            isDataLoaded = true;
        })
    }
})();

-

(function() {

    angular

    .controller('ChildController', ChildController)

    ChildController.$inject = ['$controller', '$scope', 'myFactory'];

    function ChildController($controller, $scope, myFactory) {

        $controller('ParentController', {$scope: $scope});

        var TEMPLATE = 'SCREEN';

        // ************** M A I N **************

        myFactory.getResults(URL, vm);
    }

})();

现在按我的预期工作。

当我用 ParentController 注入 ChildController 时,我真的需要注入 $scope 吗?我实际上正在使用vm。另外,我还需要注入 $location 吗?在这个例子中,当我执行我的代码时,我不得不在 ChildController 中再次使用 var URL = $location.url();,我希望从 ParentController 继承值。

所以问题是,如果我这样工作,我是否只能从 $scope 获取值? vm呢?那么像var isDataLoaded这样在vm之外声明的变量/函数呢? 我很感激对此的一些见解。这是正确的方法吗? 非常感谢。

编辑:好的,我发现了如何使用我的 ControllerAs 语法。子控制器中的代码如下:

function ChildController($controller, $scope, myFactory) {

        $controller('ParentController as vm', {$scope: $scope});

        var vm = $scope.vm;

        var TEMPLATE = 'SCREEN';

        // ************** M A I N **************

        myFactory.getResults(URL, vm);
    }

但我仍然需要找到一种方法来恢复父控制器中的常规 var/functions。有任何想法吗?能干干净净吗?

【问题讨论】:

    标签: angularjs controller


    【解决方案1】:

    我建议您在两个类之间实现通常的 javascript 继承机制。在 ChildController 构造函数中,您将执行 ParentController 构造函数并将注入的参数传递给它(不使用$controller 服务)。 我创建了简单的 example (与您的逻辑相去甚远,但将其视为模式)。我有两个控制器:ParentController 和 ChildController,它们继承自第一个。我只使用了带有$scope$interval 的 ChildController 和名称为“myservice”的自定义服务(所有这些都只需要举例)。您可以看到我使用了来自父控制器和子控制器的方法和字段。我的应用程序的逻辑非常简单:您可以将新项目添加到集合(通过 ParentController)并使用日志记录删除它们(通过 ChildController)。

    在这种情况下,我建议您将 ChildController as ctrl 用于数据绑定而不是 $scope,因为它更符合继承范例(我们继承控制器(ctrl)而不是 $scope)。

    附:如果您要经常使用继承,我建议您使用 TypeScript - 它以 c# 风格为这个问题提供了非常简单灵活的解决方案。

    Controllers.js

    function ParentController(myservice, $scope, $interval) {
      this.newOne={};
      this.lastacivity={};
      this.$interval = $interval;
      this.items = myservice();
    }
    
    ParentController.prototype.Log = function(item){
      var self = this;
      this.$interval(function(){
          console.log(item);
          self.lastacivity = item;
        }, 100, 1);
    }
    ParentController.prototype.AddNew = function (Name, Age) {
      var newitem = {
          name: this.newOne.Name,
          age: this.newOne.Age
        }
        this.items.push(newitem);
        this.Log(newitem);
    }
    
    function ChildController(myservice, $scope, $interval) {
        //Transfering myservice, $scope, $interval from ChildController to ParentController constructor,
        //also you can pass all what you want: $http, $location etc.
        ParentController.apply(this, [myservice, $scope, $interval]);
    }        
    ChildController.prototype = Object.create(ParentController.prototype)
    
    //your ChildController's own methods
    ChildController.prototype.Remove = function (item) {
        this.items.splice(this.items.indexOf(item), 1);
        this.Log(item);
    }
    

    script.js

    (function(angular) {
      'use strict';
    angular.module('scopeExample', []).factory('myservice', function() {
      var items = [
              {name:"Mike",age:21},
              {name:"Kate",age:22},
              {name:"Tom",age:11}
            ];
      return function(){
          return items;
      }
    }).controller('ChildController', ['myservice', '$scope', '$interval', ChildController]);
    })(window.angular);
    

    HTML

    <body ng-app="scopeExample">
      <div ng-controller="ChildController as ctrl">
        <label>Name</label>
        <input type='text' ng-model='ctrl.newOne.Name'/>
        <label>Age</label>
        <input type='text' ng-model='ctrl.newOne.Age'/>
        <input type='button' value='add' ng-click='ctrl.AddNew()' ng-disabled="!(ctrl.newOne.Name && ctrl.newOne.Age)"/>
        <br>
        <br>
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Age</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            <tr ng-repeat="item in ctrl.items">
              <td>{{item.name}}</td>
              <td>{{item.age}}</td>
              <td>
                <input type='button' value='X' ng-click='ctrl.Remove(item)'/>
              </td>
            </tr>
          </tbody>
        </table>
        <p>{{ctrl.lastacivity | json}}</p>
    </div>
    </body>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-10-14
      • 2021-11-05
      • 2015-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-22
      相关资源
      最近更新 更多