angularjs with oop inheritance in action

后端 未结 3 1679
终归单人心
终归单人心 2020-12-07 08:31

Abstract

I\'m working on an application that uses angular as a client side framework, angular currently rocks and I\'m really happy using it, though now I find tha

相关标签:
3条回答
  • 2020-12-07 08:57

    I think your guesses are pretty good and I played with a few approaches like that, but they all turned out more verbose than I had hoped.

    I had a problem where I had developed a complex dialog as a tab in our admin interface, but I wanted an almost identical dialog in a popup in the user section, but the data would be populated from a different source and there would be a few additional buttons. Basically a great candidate for classical inheritance. For the UI side I used a template which was included in two places with different controllers. But to avoid duplicating the complex UI logic in the controllers I wanted to use inheritance.

    The scope inheritance method relies somewhat on the structure of the application and wasn't appropriate because the two UIs were in effectively different applications. The approach of putting reused code into services would end up being verbose as I would have needed to have each controller method call an equivalent method on the service. So I used the following simple approach to JavaScript inheritance:

    /**
     * Effective base class for Thing Controllers.
     * This should be considered abstract since it does not define
     * $scope.readData() or $scope.saveData() which may be called from its
     * other functions.
     */
    function BaseThingController($scope, $http){
        $scope.data = []; // local data store;
        $scope.validateForm(){...}
        $scope.edit(){...}
        $scope.cancel(){...}
        $scope.reset(){...}
        $scope.otherMethod1(){...}
        $scope.otherMethod2(){...}
        $scope.otherMethod3(){...}
    }
    
    /**
     * AdminThingController effectively extends BaseThingController
     */
    function AdminThingController($scope, $http){
        // Calling BaseThingController as a function defines all the needed 
        // functions and properties in our scope.
        BaseThingController($scope, $http)
    
        $scope.readData(){
           // $scope.data = data from admin data source
        }
    
        $scope.saveData(newData){
           // save to special admin service
        }
    
        // initialize local data
        $scope.readData()
    }
    
    /**
     * UserThingController effectively extends BaseThingController
     */
    function UserThingController($scope, $http){
        // Calling BaseThingController as a function defines all the needed 
        // functions and properties in our scope.
        BaseThingController($scope, $http)
    
        $scope.readData(){
           // $scope.data = data from user data source
        }
    
        $scope.saveData(newData){
           // save to user service
        }
    
       /**
        * Overriding base class behaviour here
        */
       $scope.otherMethod1(){...}
    
        // initialize local data
        $scope.readData()
    
    }
    

    So I've not used prototype inheritance as the $scope is readily available. But I have gained all the behaviour from the base controller and only added or overridden what I want to. My views could be configured with either controller and would work with no modifications.

    0 讨论(0)
  • 2020-12-07 08:58

    Let me give you my opinion on Angular / inheritance situation.

    You don't do class/prototypical inheritance in Angular.js. It can be hard to test, and that is a problem. For those, who are looking for 'inheritance' in Angular, I recommend this:

    Your base class is the controller. The controller is an abstract model anyways, so it is perfect for that purpose. Use a $scope.init() function in your controller, but don't call it from there!

    If you want to 'extend' your controller's functionality, use directives. In you directive link() function, call the controller's $scope.init(). (when compiling, angular runs controllers first, and directive link functions after). If scope had a $scope.name='base', in the directive link you will be able to redefine $scope.name=child, and after that, run $scope.init().

    But wait! But this only allows a single-level inheritance. - Yes, thats true. But if you are looking for multilevel inheritance, you should use Services.

    Multilevel inheritance is nothing else, but sharing the same code in a hierarchical class structure. For this purpose, use Services, and throw in these services with the dependency injector into your directives. Soo easy. This should be easy to accomplish, easy to understand, and tests run smooth.

    Directives are very powerful tools, because you can dynamically combine partials with controllers.

    0 讨论(0)
  • 2020-12-07 09:02

    Your guesses sounds perfectly applicable.

    You can reuse functionality defined in parent controllers by simply calling methods attached to the parent scope:

    HTML

    <div ng-controller="ParentCtrl">
        <!-- Something here ... -->
        <div ng-controller="ChildCtrl">
            <!-- Something here ... -->
        </div>
        <!-- Something here ... -->
    </div>
    

    JavaScript

    function ParentCtrl($scope) {
        $scope.parentMethod = function () {
            //method body
        };
    }
    
    function ChildCtrl($scope) {
        $scope.childMethod = function () {
            //functionality
            $scope.parentMethod();
            //functionality
        };
    }
    

    If you want to use the JavaScript approach with prototype inheritance you can use:

    var myApp = angular.module('myApp',[]);
    
    function Parent($scope) {
        $scope.name = 'Superhero';    
    
        $scope.clickParent = function() {
            $scope.name = 'Clicked from base controller';
        }    
    }
    
    function Child($scope, $injector) {
    
        debugger;
        $injector.invoke(Parent, this, {$scope: $scope});
    
        $scope.name = 'Superhero Child';
    
        $scope.clickChild = function(){
            $scope.clickParent();
        }       
    }
    Child.prototype = Object.create(Parent.prototype);
    

    http://jsfiddle.net/mhevery/u6s88/12/

    For services, for example, you can use:

    (function () {
    
    function ParentService(arg1) {
       this.arg1 = arg1;
    }
    
    function ChildService(arg1, arg2) {
       ParentService.call(this, arg1);
       this.arg2 = arg2;
    }
    
    ChildService.prototype = new ParentService();
    
    app.service('ChildService', ChildService);
    
    }());
    

    Also check this discussion and the blog post about inheritance in AngularJS I posted.

    0 讨论(0)
提交回复
热议问题