2016-06-23 18 views
0

JS TOOLSJavascript Erstellen von dynamischen Objektklasse

Angular 1.5.x & lodash 4.x

FRAGE

Ich versuche, ein Objekt Fabrik Muster zu erstellen, das Objekt erstellt/Klassen . In meinem Beispiel unten erstelle ich Objektmodelle für Inhaltstypen, z. Artikel, Dokument, Bilder, usw. Angesichts meiner Fähigkeiten Beschränkungen replizieren ich das Artikel Beispiel unten für jeden Inhaltstyp. Gibt es in JavaScript eine Möglichkeit, eine dynamische Objektklasse mit einem eindeutigen Prototyp zu erstellen.

CURRENT ANSATZ

// constructor injection 
_Constructor.$inject = []; 
function _Constructor() { 
    function __constructor(data, keys) { 
     _.assign(this, _.pick(data, keys)); 
    } 
    return __constructor; 
} 

// one of many content type models 
Article.$inject = ['__constructor']; 
function Article(__constructor) { 
    function Article(data) { 
     var fillables = Object.freeze(['id','title','subtitle','body','body']); 
     __constructor.call(this, data, fillables); 
    } 

    Article.prototype = Object.create(__constructor.prototype); 
    Article.prototype.constructor = Article; 
    return Article; 
} 

IDEAL ERGEBNIS

Erstellen eines Inhaltstyp Modell Fabrik-Muster, das mich einzigartigen Inhaltstyp Objektmodelle erstellen können. Pseudo Beispiel:

var documentFillables = Object.freeze(['id', 'name', 'body']), 
    documentData = {id:1,name:'My Document', body: 'coolbody stuff'}, 
    Document = new ModelFactory('Document', documentData, documentFillables), 
    articleFillables = Object.freeze(['id', 'title', 'subtitle']), 
    articleData = {id:1,title:'My Article', subtitle: 'My Subtitle'}, 
    Article = new ModelFactory('Article', articleData, articleFillables); 

Hinweis ich gespielt habe, um mit merge, erweitern und zu klonen und zwar kann ich replizieren und erweitern Objekte, die ich mit einem fairen Betrag von Code-Redundanz am Ende und/oder generische Objekte, also haben viele ModelFactory() aber nein Article().

Antwort

1

Sie könnten einen Service erstellen (eine Factory, der eine Konstruktorfunktion zurückgibt), die allen Ihren Dokumenttypen gemeinsam ist.

Innerhalb dieser Funktion können Sie angular.extend verwenden, um die Standardwerte mit Ihren übergebenen Daten zu erweitern.

Achten Sie auch auf die Benennung z. Verwenden Sie nicht document, um Namenskonflikte mit dem Browser-Dokumentobjekt zu vermeiden. Deshalb habe ich es myDocument genannt.

Um erweiterte Factories zu erstellen, können Sie die Abhängigkeitsinjektion in der Factory-Funktion verwenden und die Basis erweitern (siehe Code für imageService als Beispiel).

Bitte werfen Sie einen Blick auf die Demo unten oder in diesem jsfiddle.

angular.module('demoApp', []) 
 
    .factory('content', ContentService) 
 
    .factory('article', ContentService) 
 
    .factory('myDocument', ContentService) 
 
    .factory('myImage', imageService) 
 
    .controller('mainController', MainController); 
 

 
function MainController(article, myDocument, myImage) { 
 
    console.log(new article({ 
 
    title: 'Test' 
 
    })); 
 
    console.log(new myDocument({ 
 
    title: 'second' 
 
    })); 
 
    console.log(new myImage({ 
 
    title: 'image' 
 
    })); 
 
    var newImage = new myImage({ 
 
    title: 'placeholder img', 
 
    src: 'https://placehold.it/300' 
 
    }); 
 
    console.log(newImage); 
 

 
    this.newImage = newImage; 
 
} 
 

 
function generateUUID() { 
 
    var d = new Date().getTime(); 
 
    if (window.performance && typeof window.performance.now === "function") { 
 
    d += performance.now(); //use high-precision timer if available 
 
    } 
 
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { 
 
    var r = (d + Math.random() * 16) % 16 | 0; 
 
    d = Math.floor(d/16); 
 
    return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16); 
 
    }); 
 
    return uuid; 
 
} 
 

 
/* 
 
// base not really needed, just as example 
 
function base(options) { 
 
\t angular.extend(this, { 
 
     id: generateUUID(), 
 
     title: '', 
 
     subtitle: '', 
 
     body: '' 
 
    }, options); 
 
}*/ 
 

 
function ContentService() { 
 
    return function(options) { 
 
    //base.call(this, options); 
 
    angular.extend(this, { 
 
     id: generateUUID(), 
 
     title: '', 
 
     subtitle: '', 
 
     body: '' 
 
    }, options); 
 
    }; 
 
} 
 

 
function imageService(content, $window) { 
 

 
    return function(options) { 
 
    var contentFactory = new content(options); 
 

 
    angular.extend(contentFactory, { 
 
     example: function() { 
 
     $window.alert('extended service: ' + contentFactory.title); 
 
     } 
 
    }); 
 

 
    return contentFactory; 
 
    } 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 
<div ng-app="demoApp" ng-controller="mainController as ctrl"> 
 
    <h3> 
 
    click image to test extended content class 
 
    </h3> 
 
    <img ng-src="{{ctrl.newImage.src}}" ng-click="ctrl.newImage.example()" /> 
 
    <p> 
 
    {{ctrl.newImage.title}} 
 
    </p> 
 
</div>

Verwandte Themen