SORU
30 HAZİRAN 2013, Pazar


oop kalıtım ile angularjs eylem

Özet

Üzerinde çalışıyorum kullanan bir uygulama açısal olarak istemci taraflı bir çerçeve, açısal şu anda kayalar ve ben çok mutlu kullanarak, ama şimdi bulmak çok kullanmak için kopyalama ve yapıştırma kodu isterim organize sınıf hiyerarşisi. Örneğin diyaloglar ortak bir set işlevi, ihtiyaçları için açılacak, kapalı, kod sağlar typeahead işlevselliği de bir ilk aday miras bazı üst BaseTypeaheadClass, ama yine de bir şey bulamadım açısal standart şekilde düzenlenmesi bu hiyerarşileri. Her iki denetleyicileri, hizmet sağlayıcıları fonksiyonları yani benim soru prototype, yoluyla uzatılabilir: sıradan javascript kullanın

Soru

Benim sınıf fonksiyonlar organizasyon, açısal yol ne orada başka bir sınıf türetmek için izin veren standart mekanizmaları vardır

S. S.

Sorun benim tahmin

  • Belirli bir sınıf gerekli olacak hizmetleri, kolayca herhangi bir denetleyici veya diğer hizmetler enjekte edilecek bir sonucu olarak temel sınıflar uygulama tanımlayın
  • OOP servis tanımlamak ve define, derive, vb gibi yöntemleri bulunur. temel / türetilmiş sınıfları oluşturmak için kullanılır

Teşekkür ederim


Edit

Biraz zaman başlangıçta sorumu sordum ne zaman zaman geçti. O zamandan bu yana çok sevdiğim, başarılı bir şekilde çeşitli projelerde kullanıyorum ve herkes ile paylaşmak isteyen bir yaklaşım ile dışarı geldi.

Şu anda açısal yok, verdiğiniz yapıları için organize sınıf hiyerarşileri ve ne yazık bu yana daha az ya da daha geniş bir uygulama olamaz yeterli sadece Model/Görünüm/Denetleyici/... yapıları, daha organize olmuş koduna OOP nesne.

Oldukça uzun bir süre için web geliştirme alanında çalışıyorum zaten ağır ve JavaScript ile OOP yararlandığını bile bir kurumsal proje görmedim. Gördüm ne güzel organize sunucu tarafında büyük / veritabanı tarafında mantık sonsuz spagetti javascript istemci tarafında çerçeveler ve kütüphaneler, Hayvanat Bahçesi ile yağlanmış yakındı.

Hayır MVVM, knockout.js omurga, Diğer gibi MVP çerçeveler... gibi OOP değiştirme yeteneğine sahiptirler. Eğer Classses, Nesneler, Kalıtım, Soyutlama, başın büyük belada Polimorfizmi gibi orientired programlama temel ilkeleri kullanıyorsanız, sona erecek ne mega uzun bir javascript spagetti.

Açısal ilişkin bir çerçeve çok farklı olduğunu düşünüyorum knockout.js / backbone.js başka MVV-hiçbir şey ama benim uygulamaya göre çerçeveler de gümüş kurşun OOP yerine koymak mümkün değildir. Açısal ile OOP kullanmamaya çalışıyorum zaman çoğunlukla mantık denetleyicileri yer alan yinelenen ile bitiriyorum. Ve ne yazık ki yok (buldum) temiz ve bu sorunu dayak açısal yön yoktur.

Ama bu sorun çözüldü başarıyla (sanırım) var.

Sadece John Resig's Simple JavaScript Inheritance (https://github.com/tracker1/core-js/blob/master/js-extensions/040-Class.js) uygulayan, zerro-bağımlılık lib kompakt kullandım. Bu kütüphane yardımı ile başka bir deyişle bunu sunucu tarafında alışık olduğum her şeyi / soyut yöntemler oluşturmak / miras / onları geçersiz kılma oluşturmak için başardı.

İşte bir örnek kullanımı:

Application.factory('SomeChildObject', ['$http', 'SomeParentClass', function ($http, SomeParentClass) {
    var SomeChildClass = SomeParentClass.extend({
        init: function() { // Constructor
            this._super.init(123, 231); // call base constructor
        },
        someFunction: function() {
            // Notice that your OOP now knows everything that can be injected into angular service, which is pretty cool :)
            $http({method: 'GET', url: '/someUrl'}).then(function(){
                this._super.someFunction(); // call base function implementation
            });
        }
    });

    // return new SomeChildClass(); // We are not returning instance here!

    return SomeChildClass; // Service is a function definition not an instance of an object
}]);

// So now we can both use this service in angular and have the ability to extend it using the `extend` method call, like so:
Application.controller('MegaController', ['$scope', 'SomeChildClass', function ($scope, SomeChildClass) {
    $scope.someObject = new SomeChildClass();
}]);

OOP Açısal birlikte oynamak çok güzel, nesnelerin altında açısal bağlam olabilir yararlanmak bağımlılık enjeksiyon yoluyla hizmetleri otomatik olarak, o yüzden gerek yok enjekte örnekleri içine OOP kurucular ve bu gerçek yapar senin OOP hiyerarşi çok ince ve ücretsiz alakasız şeyler gerekiyor (ve) idare tarafından angular.js

Bu yaklaşım ile oynamak ve burada bir geri besleme karşılaştı . kazandın ya da sorunları sonuçlar ver

Teşekkür ederim

Başka bir düzenleme

Son zamanlarda aşağıdaki gibidir: orijinal class.js birkaç sorun uygulanmasına karşı karşıya geldim

1) Eğer diğer yöntemler için geri çağrıları örnek yöntemleri için bir başvuru geçirmeden, bu yöntemler onları çalışmak için beklediğiniz şekilde değil işe yarayabilir. this referans gevşek olacak. Böyle bir durumda this içinde bulunduğunuz nesneyi görmek için bekliyor olacak ama Window veya başka bir bağlam, geri arama yöntemi çağrıları nasıl bağlı olarak, nesne ya da üst düzeyde olacaktır. Mimarlık JavaScript sayesinde oluyor. Sipariş için mücadele, bu sorun, bir özel ClassMember fonksiyonudur sağlanan bildirir Class bağlama yöntemi için nesne bağlamında zaman olarak yaratmıştır (kontrol Usage aşağıda daha fazla bilgi).

2) Belli ki Class.js orijinal uygulama tipi denetleyici yöntemi tanımlamalar açısal yani hakkında hiçbir şey bilmiyor

Class.extend('YourClassDisplayName', {
    ctor: function () {
        // Some useful constructor logic
    },
    controller: ['$scope', '$attrs', function ($scope, $attrs) {
        // Do smth. with $scope and $attrs
    }]
});

Geçerli uygulama yukarıdaki sözdizimi anlar

3) kullanırken yukarıdaki yaklaşım olmadan işleme uygun olacağını açısal $$annotate'süreci çok atıfta yukarıdaki örnek olur yapmak imkansız enjekte $scope $attrs ClassMember yöntem veya geçersiz yöntemi kullanarak this.base(...) çağırır. Bu da sabit.

Sorunlar:

1) kullanırken this.base(...) içinde zaman uyumsuz işlem işleyicisi (gibi bir şey $http.get(..., function() { self.base(...); })) lütfen unutmayın this.base(...) Arama Bir ömür boyu sınırlı ve en kısa sürede bu yöntem döndürür this.base(...) durur mevcut. Eğer asenkron moda temel yöntemlerini çağırmayı planlıyorsanız temel yöntemi için referans açıkça kaydetmelisiniz. ben.e:

...
var self = this;
var base = this.base;
...
$http.get(..., function () {
    base.call(self, ...); // or base.apply(self, ...), or base() if you don't care about `this`
})

Yukarıdaki tüm sorunları (JavaScript mimarisi nedeniyle çözülemez hangisi yakaladım hariç) kararlaştırdım ve herkesle paylaşmak istiyorum, faydalı olacağını umuyoruz:

/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 *
 * Inspired by base2 and Prototype

 * Angular adaptations by Denis Yaremov http://github.com/lu4
 * Usage:
 ---------------------------------

   var X = Class.extend('X', {
       ctor: function () {
           this.name = "I'm X";
       },

       myOrdinaryMethod: function (x, y, z) {
           console.log([this.name, x, y, z]);
       },

       myClassMemberMethod: ClassMember(function (x, y, z) {
           console.log([this.name, x, y, z]);
       })
   });

   var Y = Class.extend('Y', {
       ctor: function () {
           this.name = "I'm Y";
       },

       myOrdinaryMethod: function (x, y, z) {
           console.log([this.name, x, y, z]);
       },

       myClassMemberMethod: ClassMember(function (x, y, z) {
           console.log([this.name, x, y, z]);
       })
   });

   var x = new X();
   var y = new Y();

   x.myClassMemberMethod('a', 'b', 'c'); // ["I'm X", "a", "b", "c"] 
   y.myClassMemberMethod('u', 'v', 'm'); // ["I'm Y", "u", "v", "m"] 

   x.myOrdinaryMethod('a', 'b', 'c'); // ["I'm X", "a", "b", "c"] 
   y.myOrdinaryMethod('u', 'v', 'm'); // ["I'm Y", "u", "v", "m"] 

   y.theirOrdinaryMethod = x.myOrdinaryMethod;
   y.theirClassMemberMethod = x.myClassMemberMethod;

   y.theirOrdinaryMethod('a', 'b', 'c'); // ["I'm Y", "a", "b", "c"] 
   y.theirClassMemberMethod('u', 'v', 'm'); // ["I'm X", "u", "v", "m"]

*/

angular.module('app').factory('ClassMember', function () {
    return function ClassMember(fn) {
        if (this instanceof ClassMember) {
            this.fn = fn;
        } else {
            return new ClassMember(fn);
        }
    };
});

angular.module('app').factory('Class', function (ClassMember) {
    var runtime = { initializing: false },
        fnTest = /xyz/.test(function() { xyz; }) ? /\bbase\b/ : /.*/,
        FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m,
        STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;

    var toString = Object.prototype.toString;

    // The base Class implementation (does nothing)
    function Class() { };

    Class.members = { };

    // Create a new Class that inherits from this class
    Class.extend = function extend(displayName, properties) {
        var array;

        var targetMembers = {};
        var sourceMembers = this.members;

        for (var memberName in sourceMembers) {
            if (sourceMembers.hasOwnProperty(memberName)) {
                targetMembers[memberName] = sourceMembers[memberName];
            }
        }

        var base = this.prototype;

        // Instantiate a base class (but only create the instance,
        // don't run the ctor constructor)
        runtime.initializing = true;
        var prototype = new this();
        runtime.initializing = false;

        // Copy the properties over onto the new prototype
        for (var name in properties) {
            if (properties.hasOwnProperty(name)) {
                // Check if we're overwriting an existing function
                var property = properties[name];

                // Support angular's controller/service/factory declaration notation
                if (toString.call(property) === '[object Array]') {
                    array = property;

                    var item = array[array.length - 1];

                    if (toString.call(item) === '[object Function]' || item instanceof ClassMember) {
                        property = array[array.length - 1];
                    } else {
                        array = null;
                    }
                } else {
                    array = null;
                }

                var isClassMember = property instanceof ClassMember;

                if (isClassMember) {
                    property = property.fn;
                }

                if (typeof property === "function") {
                    if (typeof base[name] === "function" && fnTest.test(property)) {
                        property = (function (propertyName, fn) {
                            var args = fn.toString().replace(STRIP_COMMENTS, '').match(FN_ARGS)[1];
                            return (new Function('propertyName', 'fn', 'base', 'return function ('   args   ') {\n\
                                    var prevBase = this.base;\n\
                                    var hasBase = "base" in this;\n\
\n\
                                    // Add a new .base() method that is the same method\n\
                                    // but on the super-class\n\
\n\
                                    this.base = base[propertyName];\n\
\n\
                                    // The method only need to be bound temporarily, so we\n\
                                    // remove it when we\'re done executing\n\
                                    var ret = fn.call(this'   (!!args ? (', '   args) : args)   ');\n\
\n\
                                    if (hasBase) {\n\
                                        this.base = prevBase;\n\
                                    } else {\n\
                                        delete this["base"];\n\
                                    }\n\
                                    return ret;\n\
                                }'))(propertyName, fn, base);
                        })(name, property);
                    }

                    if (isClassMember) {
                        targetMembers[name] = property;
                    } else if (name in targetMembers) {
                        delete targetMembers[name];
                    }

                    if (array) {
                        array[array.length - 1] = property;

                        property = array;
                    }

                    prototype[name] = property;
                } else {
                    prototype[name] = property;
                }
            }
        }

        var membersArray = [];
        for (var i in targetMembers) {
            if (targetMembers.hasOwnProperty(i)) {
                membersArray.push({ name: i, fn: targetMembers[i] });
            }
        }

        // All construction is actually done in the ctor method
        var ChildClass = (new Function("runtime", "members", "FN_ARGS", "STRIP_COMMENTS", "return function "   (displayName || "Class")   "() {\n\
            if (!runtime.initializing && this.ctor)\n\
            {\n\
                var length = members.length;\n\
                for (var i = 0; i < length; i  )\n\
                {\n\
                    var item = members[i];\n\
                    this[item.name] = (function (me, fn) {\n\
                        var args = fn.toString().replace(STRIP_COMMENTS, '').match(FN_ARGS)[1];\n\
                        return args ? (new Function('me', 'fn', 'return function ('   args   ') { return fn.call(me, '   args   '); }'))(me, fn) : function () { return fn.call(me); };\n\
                    })(this, item.fn);\n\
\n\
                }\n\
                this.ctor.apply(this, arguments);\n\
            }\n\
        }"))(runtime, membersArray, FN_ARGS, STRIP_COMMENTS);

        ChildClass.members = targetMembers;

        // Populate our constructed prototype object
        ChildClass.prototype = prototype;

        // Enforce the constructor to be what we expect
        ChildClass.prototype.constructor = ChildClass;

        // And make this class extendable
        ChildClass.extend = extend;

        return ChildClass;
    };

    return Class;
});

CEVAP
30 HAZİRAN 2013, Pazar


Tahminlerin tam olarak uygulanabilir görünüyor.

İşlevsellik sadece yöntemleri üst kapsam bağlı çağırarak üst denetleyicileri tanımlanan yeniden kullanabilirsiniz:

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
    };
}

Eğer prototip mirası ile JavaScript yaklaşım kullanmak isterseniz kullanabilirsiniz:

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/

Örneğin hizmetler için kullanabilirsiniz:

(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);

}());

Ayrıca this tartışma kontrol edin ve blog post about inheritance in AngularJS yayınlanmıştır.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Anthony Cumia

    Anthony Cumi

    5 EYLÜL 2006
  • Eric Magidson

    Eric Magidso

    4 Ocak 2009
  • Wild Academy

    Wild Academy

    8 Aralık 2009