variable Allgemein akzeptierte Best Practices zur Code-Organisation in JavaScript




javascript practice (23)

Da JavaScript-Frameworks wie jQuery Client-seitige Web-Anwendungen reicher und funktionaler machen, habe ich ein Problem festgestellt ...

Wie in der Welt halten Sie das organisiert?

  • Setzen Sie alle Ihre Handler an einen Ort und schreiben Sie Funktionen für alle Veranstaltungen?
  • Erstellen Sie Funktionen / Klassen, um all Ihre Funktionen zu integrieren?
  • Schreibe wie verrückt und hoffe nur, dass es für das Beste klappt?
  • Aufgeben und eine neue Karriere machen?

Ich erwähne jQuery, aber es ist wirklich jeder JavaScript-Code im Allgemeinen. Ich stelle fest, dass es immer schwieriger wird, die Skriptdateien zu verwalten oder zu finden, wonach Sie suchen. Das wahrscheinlich größte Problem, das ich gefunden habe, ist, dass es so viele Möglichkeiten gibt, das Gleiche zu tun. Es ist schwer zu wissen, welches die gängigste Best Practice ist.

Gibt es allgemeine Empfehlungen, wie Sie Ihre .js- Dateien so schön und ordentlich wie den Rest Ihrer Anwendung aufbewahren können? Oder ist das nur eine Frage der IDE? Gibt es eine bessere Option da draußen?

BEARBEITEN

Bei dieser Frage ging es mehr um die Code-Organisation und nicht um die Organisation von Dateien. Es gab einige wirklich gute Beispiele für das Zusammenführen von Dateien oder Teilen von Inhalten.

Meine Frage ist: Was ist der gängigste Best Practice-Weg, um Ihren eigentlichen Code zu organisieren? Was ist Ihre Art oder sogar eine empfohlene Methode, um mit Seitenelementen zu interagieren und wiederverwendbaren Code zu erstellen, der nicht miteinander in Konflikt steht?

Einige Leute haben Namespaces aufgelistet, was eine gute Idee ist. Was sind andere Wege, genauer gesagt mit Elementen auf der Seite umzugehen und den Code organisiert und ordentlich zu halten?


Ich denke, dass dies DDD (Domain-Driven Design) betrifft. Die Anwendung, an der ich arbeite, gibt zwar Hinweise auf eine formale API, gibt jedoch Hinweise über den serverseitigen Code (Klassen- / Dateinamen usw.). Auf diese Weise erstellte ich ein Objekt der obersten Ebene als Container für die gesamte Problemdomäne. Dann habe ich Namespaces dort eingefügt, wo sie benötigt wurden:

var App;
(function()
{
    App = new Domain( 'test' );

    function Domain( id )
    {
        this.id = id;
        this.echo = function echo( s )
        {
            alert( s );
        }
        return this;
    }
})();

// separate file
(function(Domain)
{
    Domain.Console = new Console();

    function Console()
    {
        this.Log = function Log( s )
        {
            console.log( s );
        }
        return this;
    }
})(App);

// implementation
App.Console.Log('foo');

Ich versuche zu vermeiden, irgendein Javascript mit dem HTML einzuschließen. Der gesamte Code ist in Klassen eingekapselt und jede Klasse befindet sich in einer eigenen Datei. Für die Entwicklung habe ich separate <script> -Tags, die jede js-Datei einschließen, aber sie werden in ein einziges größeres Paket für die Produktion zusammengeführt, um den Overhead der HTTP-Anfragen zu reduzieren.

Normalerweise habe ich für jede Anwendung eine einzige "Haupt" -JS-Datei. Also, wenn ich eine "Umfrage" -Anwendung schreiben würde, hätte ich eine js-Datei namens "survey.js". Dies würde den Einstiegspunkt in den jQuery-Code enthalten. Ich erstelle während der Instanziierung jQuery-Referenzen und gebe sie dann als Parameter an meine Objekte weiter. Dies bedeutet, dass die JavaScript-Klassen "rein" sind und keine Verweise auf CSS-IDs oder Klassennamen enthalten.

// file: survey.js
$(document).ready(function() {
  var jS = $('#surveycontainer');
  var jB = $('#dimscreencontainer');
  var d = new DimScreen({container: jB});
  var s = new Survey({container: jS, DimScreen: d});
  s.show();
});

Ich finde auch Namenskonventionen wichtig für die Lesbarkeit. Zum Beispiel: Ich stelle 'j' allen jQuery-Instanzen voran.

Im obigen Beispiel gibt es eine Klasse namens DimScreen. (Angenommen, dies blendet den Bildschirm aus und öffnet eine Warnmeldung.) Er benötigt ein div-Element, das vergrößert werden kann, um den Bildschirm abzudecken, und fügt dann eine Warnmeldung hinzu, sodass ich ein jQuery-Objekt übergebe. jQuery hat ein Plug-in-Konzept, aber es schien begrenzend (zB Instanzen sind nicht persistent und können nicht zugegriffen werden) ohne wirklichen Vorteil. Die DimScreen-Klasse wäre also eine Standard-JavaScript-Klasse, die zufälligerweise jQuery verwendet.

// file: dimscreen.js
function DimScreen(opts) { 
   this.jB = opts.container;
   // ...
}; // need the semi-colon for minimizing!


DimScreen.prototype.draw = function(msg) {
  var me = this;
  me.jB.addClass('fullscreen').append('<div>'+msg+'</div>');
  //...
};

Ich habe einige ziemlich komplexe Anwendungen mit diesem Ansatz erstellt.


Schauen Sie sich JavasciptMVC an .

Sie können :

  • Teilen Sie Ihren Code in Modell-, Ansichts- und Controller-Ebenen auf.

  • Komprimiere den gesamten Code in eine einzige Produktionsdatei

  • Code automatisch generieren

  • Erstellen und Ausführen von Komponententests

  • und vieles mehr...

Das Beste daran ist, dass es jQuery verwendet, so dass Sie auch andere jQuery-Plugins nutzen können.


Es wäre viel schöner, wenn Javascript Namespaces eingebaut hätte, aber ich finde, dass das Organisieren von Dingen wie Dustin Diaz here mir sehr hilft.

var DED = (function() {

    var private_var;

    function private_method()
    {
        // do stuff here
    }

    return {
        method_1 : function()
            {
                // do stuff here
            },
        method_2 : function()
            {
                // do stuff here
            }
    };
})();

Ich habe verschiedene "Namespaces" und manchmal einzelne Klassen in separaten Dateien abgelegt. Normalerweise beginne ich mit einer Datei und da eine Klasse oder ein Namespace groß genug ist, um dies zu rechtfertigen, separiere ich sie in eine eigene Datei. Ein Tool, um alle Ihre Dateien für die Produktion zu kombinieren, ist ebenfalls eine ausgezeichnete Idee.



Die Code-Organisation erfordert die Übernahme von Konventionen und Dokumentationsstandards:
1. Namespace-Code für eine physische Datei;

Exc = {};


2. Gruppenklassen in diesen Namespaces Javascript;
3. Setze Prototypen oder verwandte Funktionen oder Klassen zum Darstellen von realen Objekten;

Exc = {};
Exc.ui = {};
Exc.ui.maskedInput = function (mask) {
    this.mask = mask;
    ...
};
Exc.ui.domTips = function (dom, tips) {
    this.dom = gift;
    this.tips = tips;
    ...
};


4. Legen Sie Konventionen fest, um den Code zu verbessern. Zum Beispiel gruppieren Sie alle internen Funktionen oder Methoden in seinem Klassenattribut eines Objekttyps.

Exc.ui.domTips = function (dom, tips) {
    this.dom = gift;
    this.tips = tips;
    this.internal = {
        widthEstimates: function (tips) {
            ...
        }
        formatTips: function () {
            ...
        }
    };
    ...
};


5. Machen Sie Dokumentation von Namespaces, Klassen, Methoden und Variablen. Wenn nötig, besprechen Sie auch einen Teil des Codes (einige FIs und Fors, sie implementieren normalerweise wichtige Logik des Codes).

/**
  * Namespace <i> Example </i> created to group other namespaces of the "Example".  
  */
Exc = {};
/**
  * Namespace <i> ui </i> created with the aim of grouping namespaces user interface.
  */
Exc.ui = {};

/**
  * Class <i> maskdInput </i> used to add an input HTML formatting capabilities and validation of data and information.
  * @ Param {String} mask - mask validation of input data.
  */
Exc.ui.maskedInput = function (mask) {
    this.mask = mask;
    ...
};

/**
  * Class <i> domTips </i> used to add an HTML element the ability to present tips and information about its function or rule input etc..
  * @ Param {String} id - id of the HTML element.
  * @ Param {String} tips - tips on the element that will appear when the mouse is over the element whose identifier is id <i> </i>.
  */
  Exc.ui.domTips = function (id, tips) {
    this.domID = id;
    this.tips = tips;
    ...
};


Dies sind nur einige Tipps, aber das hat sehr geholfen, den Code zu organisieren. Denken Sie daran, dass Sie Disziplin haben müssen, um erfolgreich zu sein!


I'm using this little thing. It gives you 'include' directive for both JS and HTML templates. It eleminates the mess completely.

https://github.com/gaperton/include.js/

$.include({
    html: "my_template.html" // include template from file...
})
.define( function( _ ){ // define module...
    _.exports = function widget( $this, a_data, a_events ){ // exporting function...
        _.html.renderTo( $this, a_data ); // which expands template inside of $this.

        $this.find( "#ok").click( a_events.on_click ); // throw event up to the caller...
        $this.find( "#refresh").click( function(){
            widget( $this, a_data, a_events ); // ...and update ourself. Yep, in that easy way.
        });
    }
});

In meinem letzten Projekt -Viajeros.com- habe ich eine Kombination verschiedener Techniken verwendet. Ich würde nicht wissen, wie man eine Web-App organisiert - Viajeros ist eine Social-Networking-Site für Reisende mit gut definierten Abschnitten, so dass es leicht ist, den Code für jeden Bereich zu trennen.

Ich benutze die Namespace-Simulation und das verzögerte Laden von Modulen gemäß dem Site-Abschnitt. Auf jeder Seite load deklariere ich ein "vjr" -Objekt und lade immer eine Menge allgemeiner Funktionen (vjr.base.js). Dann entscheidet jede HTML-Seite, welche Module mit einem einfachen benötigen:

vjr.Required = ["vjr.gallery", "vjr.comments", "vjr.favorites"];

Vjr.base.js bekommt jeden vom Server gezippt und führt sie aus.

vjr.include(vjr.Required);
vjr.include = function(moduleList) {
  if (!moduleList) return false;
  for (var i = 0; i < moduleList.length; i++) {
    if (moduleList[i]) {
      $.ajax({
        type: "GET", url: vjr.module2fileName(moduleList[i]), dataType: "script"
      });
    }
  }
};

Jedes "Modul" hat diese Struktur:

vjr.comments = {}

vjr.comments.submitComment = function() { // do stuff }
vjr.comments.validateComment = function() { // do stuff }

// Handlers
vjr.comments.setUpUI = function() {
    // Assign handlers to screen elements
}

vjr.comments.init = function () {
  // initialize stuff
    vjr.comments.setUpUI();
}

$(document).ready(vjr.comments.init);

Angesichts meines begrenzten Javascript-Wissens weiß ich, dass es bessere Möglichkeiten geben muss, dies zu handhaben, aber bis jetzt funktioniert es großartig für uns.


Das Befolgen von guten OO-Designprinzipien und Designmustern trägt wesentlich dazu bei, dass Ihr Code leicht zu pflegen und zu verstehen ist. Aber eines der besten Dinge, die ich in letzter Zeit entdeckt habe, sind Signale und Slots aka publish / subscribe. Sehen Sie sich http://markdotmeyer.blogspot.com/2008/09/jquery-publish-subscribe.html für eine einfache jQuery-Implementierung an.

Die Idee wird in anderen Sprachen für die GUI-Entwicklung gut verwendet. Wenn etwas Bedeutendes irgendwo in Ihrem Code passiert, veröffentlichen Sie ein globales synthetisches Ereignis, das andere Methoden in anderen Objekten abonnieren können. Dies ergibt eine ausgezeichnete Trennung von Objekten.

Ich denke Dojo (und Prototype?) Haben eine eingebaute Version dieser Technik.

siehe auch Was sind Signale und Slots?


Vor ein paar Tagen haben die Jungs von 37Signals WysiHat , mit einem Twist. Sie haben eine Bibliothek erstellt, die Javascript-Dateien mit einer Art von Pre-Prozessor-Befehlen bündelt.

Ich benutze es seitdem, um meine JS-Dateien zu trennen und sie dann am Ende als eins zusammenzuführen. Auf diese Weise kann ich Bedenken trennen und am Ende nur eine Datei haben, die durch die Pipe geht (nicht gezippt).

Überprüfen Sie in Ihren Vorlagen, ob Sie sich im Entwicklungsmodus befinden, und fügen Sie die separaten Dateien hinzu. Wenn Sie in der Produktion sind, fügen Sie die endgültige Datei hinzu (die Sie selbst erstellen müssen).


You can use jquery mx (used in javascriptMVC) which is a set of scripts that allows you to use models, views, and controllers. I've used it in a project and helped me create structured javascript, with minimal script sizes because of compression. This is a controller example:

$.Controller.extend('Todos',{
  ".todo mouseover" : function( el, ev ) {
   el.css("backgroundColor","red")
  },
  ".todo mouseout" : function( el, ev ) {
   el.css("backgroundColor","")
  },
  ".create click" : function() {
   this.find("ol").append("<li class='todo'>New Todo</li>"); 
  }
})

new Todos($('#todos'));

You can also use only the controller side of jquerymx if you aren't interested in the view and model parts.


Das Organisieren Ihres Codes in einem JQuery-zentrischen NameSpace-Pfad kann wie folgt aussehen ... und wird nicht mit anderen Javascript-APIs wie Prototype oder Ext kollidieren.

<script src="jquery/1.3.2/jquery.js" type="text/javascript"></script>
<script type="text/javascript">

var AcmeJQ = jQuery.noConflict(true);
var Acme = {fn: function(){}};

(function($){

    Acme.sayHi = function()
    {
        console.log('Hello');
    };

    Acme.sayBye = function()
    {
        console.log('Good Bye');
    };
})(AcmeJQ);

// Usage
//          Acme.sayHi();
// or
// <a href="#" onclick="Acme.sayHi();">Say Hello</a>


</script>

Hoffe das hilft.


"Schreibe wie verrückt und hoffe nur, dass es für das Beste klappt?", Ich habe ein Projekt wie dieses gesehen, das von nur zwei Entwicklern entwickelt und gewartet wurde, eine riesige Anwendung mit viel JavaScript-Code. Darüber hinaus gab es verschiedene Abkürzungen für jede denkbare jQuery-Funktion. Ich schlug vor, den Code als Plugins zu organisieren, denn das ist das Jquery-Äquivalent von Klasse, Modul, Namespace ... und dem ganzen Universum. Aber die Dinge wurden viel schlimmer, jetzt begannen sie Plugins zu schreiben, die jede Kombination von 3 Codezeilen ersetzen, die im Projekt verwendet wurden. Persönlich denke ich, dass jQuery der Teufel ist und es sollte nicht auf Projekten mit viel Javascript verwendet werden, weil es Sie ermutigt, faul zu sein und nicht daran zu denken, Code in irgendeiner Weise zu organisieren. Ich würde lieber 100 Zeilen Javascript als eine Zeile mit 40 verketteten jQuery-Funktionen lesen (ich mache keine Witze). Entgegen der landläufigen Meinung ist es sehr einfach, JavaScript-Code in Entsprechungen zu Namespaces und Klassen zu organisieren. Das tun YUI und Dojo. Sie können leicht Ihre eigenen rollen, wenn Sie möchten. Ich finde YUIs Ansatz viel besser und effizienter. Aber normalerweise brauchen Sie einen netten Editor mit Snippet-Unterstützung, um YUI-Namenskonventionen zu kompensieren, wenn Sie etwas Nützliches schreiben wollen.


I use a custom script inspired by Ben Nolan's behaviour (I can't find a current link to this anymore, sadly) to store most of my event handlers. These event handlers are triggered by the elements className or Id, for example. Beispiel:

Behaviour.register({ 
    'a.delete-post': function(element) {
        element.observe('click', function(event) { ... });
    },

    'a.anotherlink': function(element) {
        element.observe('click', function(event) { ... });
    }

});

I like to include most of my Javascript libraries on the fly, except the ones that contain global behaviour. I use Zend Framework's headScript() placeholder helper for this, but you can also use javascript to load other scripts on the fly with Ajile for example.


Dojo hatte das Modulsystem vom ersten Tag an. In der Tat gilt es als Eckpfeiler von Dojo, der Klebstoff, der alles zusammenhält:

Module verwenden Dojo erreicht folgende Ziele:

  • Namespaces für Dojo-Code und benutzerdefinierten Code ( dojo.declare() ) - verschmutzen Sie nicht den globalen Platz, Koexistenz mit anderen Bibliotheken und nicht-Dojo-bewußten Code des Benutzers.
  • Laden von Modulen synchron oder asynchron nach Name ( dojo.require() ).
  • Benutzerdefinierte Builds durch Analysieren von Modulabhängigkeiten, um eine einzelne Datei oder eine Gruppe voneinander abhängiger Dateien (so genannte Layer) zu erstellen, die nur das enthält, was Ihre Webanwendung benötigt. Benutzerdefinierte Builds können Dojo-Module und vom Kunden bereitgestellte Module enthalten.
  • Transparenter CDN-basierter Zugriff auf Dojo und Benutzercode. Sowohl AOL als auch Google tragen Dojo auf diese Weise, aber einige Kunden tun das auch für ihre eigenen Webanwendungen.

Ein gutes Prinzip von OO + MVC würde auf jeden Fall einen langen Weg für die Verwaltung einer komplexen Javascript-App gehen.

Im Grunde organisiere ich meine App und JavaScript auf das folgende bekannte Design (das von meinen Desktop-Programmierungstagen bis zum Web 2.0 zurückreicht)

Beschreibung für die numerischen Werte auf dem Bild:

  1. Widgets, die die Ansichten meiner Anwendung darstellen. Dies sollte sauber erweiterbar und getrennt sein, was zu einer guten Trennung führt, die MVC zu erreichen versucht, anstatt mein Widget in einen Spaghetti-Code umzuwandeln (äquivalent in der Web-App, einen großen Javascript-Block direkt in HTML zu setzen). Jedes Widget kommuniziert über andere, indem es auf das von anderen Widgets generierte Ereignis hört und so die starke Kopplung zwischen Widgets reduziert, die zu nicht mehr handhabbarem Code führen kann (erinnern Sie sich an den Tag des Hinzufügens von onclick an alle globalen Funktionen im Skript-Tag? Urgh ...)
  2. Objektmodelle, die die Daten darstellen, die ich in den Widgets auffüllen und an den Server übergeben möchte. Durch die Kapselung der Daten in ihr Modell wird die Anwendung zu Datenformat-Agnostik. Zum Beispiel: Während natürlich in JavaScript diese Objektmodelle hauptsächlich in JSON serialisiert und deserialisiert werden, wenn der Server XML für die Kommunikation verwendet, muss ich nur die Serialisierungs- / Deserialisierungsebene ändern und muss nicht unbedingt alle Widgetklassen ändern .
  3. Controller-Klassen, die die Geschäftslogik und die Kommunikation mit dem Server verwalten und gelegentlich Cache-Layer verwenden. Diese Schicht steuert das Kommunikationsprotokoll zum Server und legt die notwendigen Daten in die Objektmodelle ein
  4. Die Klassen sind sauber in die entsprechenden Namespaces eingepackt. Ich bin mir sicher, dass wir alle wissen, wie unangenehm globaler Namespace in Javascript sein kann.

In der Vergangenheit würde ich die Dateien in eine eigene js trennen und allgemeine Praxis verwenden, um OO-Prinzipien in Javascript zu erstellen. Das Problem, dass ich bald fand, dass es mehrere Möglichkeiten gibt, JS OO zu schreiben, und es ist nicht unbedingt so, dass alle Teammitglieder den gleichen Ansatz verfolgen. Als das Team größer wurde (in meinem Fall mehr als 15 Leute), wird dies kompliziert, da es keinen Standardansatz für objektorientiertes Javascript gibt. Gleichzeitig möchte ich nicht meinen eigenen Rahmen schreiben und einige Arbeiten wiederholen, von denen ich sicher bin, dass sie klüger sind als ich.

jQuery ist unglaublich schön als Javascript Framework und ich liebe es, aber je größer das Projekt wird, desto mehr brauche ich eine zusätzliche Struktur für meine Web-App, um die OO-Praxis zu standardisieren. Für mich selbst, nach mehreren Experimenten, finde ich, dass YUI3 Base und Widget ( http://yuilibrary.com/yui/docs/widget/ und http://yuilibrary.com/yui/docs/base/index.html ) Infrastruktur bietet genau was ich brauche. Wenige Gründe, warum ich sie benutze.

  1. Es bietet Namespace-Unterstützung. Eine echte Notwendigkeit für OO und ordentliche Organisation Ihres Codes
  2. Es unterstützt die Vorstellung von Klassen und Objekten
  3. Es gibt ein Standardisierungsmittel, um Instanzvariablen zu Ihrer Klasse hinzuzufügen
  4. Es unterstützt die Klassenerweiterung sauber
  5. Es bietet Konstruktor und Destruktor
  6. Es bietet Render- und Ereignisbindung
  7. Es hat ein Basis-Widget-Framework
  8. Jedes Widget kann nun mithilfe eines standardbasierten ereignisbasierten Modells miteinander kommunizieren
  9. Vor allem gibt es allen Ingenieuren einen OO-Standard für die Entwicklung von Javascript

Im Gegensatz zu vielen Ansichten muss ich nicht unbedingt zwischen jQuery und YUI3 wählen. Diese beiden können friedlich koexistieren. Während YUI3 die notwendige OO-Vorlage für meine komplexe Web-App bereitstellt, bietet jQuery meinem Team immer noch eine einfach zu verwendende JS-Abstraktion, die wir alle lieben und kennen.

Mit YUI3 habe ich MVC-Muster erstellen können, indem ich Klassen getrennt habe, die die Basis als Modell erweitern, Klassen, die Widget als Ansicht erweitern, und natürlich haben Sie Controller-Klassen, die notwendige Logik- und Server-Aufrufe machen.

Widget kann miteinander über ein ereignisbasiertes Modell kommunizieren und dem Ereignis zuhören und die erforderliche Aufgabe basierend auf der vordefinierten Schnittstelle ausführen. Einfach gesagt, es ist eine Freude für mich, OO + MVC-Struktur zu JS zu setzen.

Nur ein Disclaimer, ich arbeite nicht für Yahoo! und einfach ein Architekt, der versucht, das gleiche Problem zu lösen, das die ursprüngliche Frage aufwirft. Ich denke, wenn jemand ein äquivalentes OO-Framework findet, würde das auch funktionieren. Grundsätzlich gilt diese Frage auch für andere Technologien. Danke Gott für all die Leute, die OO Principles + MVC entwickelt haben, um unsere Programmier-Tage überschaubarer zu machen.


Erstellen Sie gefälschte Klassen und stellen Sie sicher, dass alles, was in eine separate Funktion umgewandelt werden kann, sinnvoll ist. Achten Sie auch darauf, viel zu kommentieren und nicht Spaghetti-Code zu schreiben, sondern alles in Abschnitten zu behalten. Zum Beispiel einige Unsinn-Codes, die meine Ideale darstellen. Natürlich schreibe ich im wirklichen Leben auch viele Bibliotheken, die im Grunde ihre Funktionalität umfassen.

$(function(){
    //Preload header images
    $('a.rollover').preload();

    //Create new datagrid
    var dGrid = datagrid.init({width: 5, url: 'datalist.txt', style: 'aero'});
});

var datagrid = {
    init: function(w, url, style){
        //Rendering code goes here for style / width
        //code etc

        //Fetch data in
        $.get(url, {}, function(data){
            data = data.split('\n');
            for(var i=0; i < data.length; i++){
                //fetching data
            }
        })
    },
    refresh: function(deep){
        //more functions etc.
    }
};

You don't mention what your server-side language is. Or, more pertinently, what framework you are using -- if any -- on the server-side.

IME, I organise things on the server-side and let it all shake out onto the web page. The framework is given the task of organising not only JS that every page has to load, but also JS fragments that work with generated markup. Such fragments you don't usually want emitted more than once - which is why they are abstracted into the framework for that code to look after that problem. :-)

Für End-Seiten, die ihren eigenen JS ausgeben müssen, finde ich normalerweise, dass es eine logische Struktur im generierten Markup gibt. Ein solcher lokalisierter JS kann oft am Anfang und / oder am Ende einer solchen Struktur zusammengesetzt werden.

Beachten Sie, dass Sie dadurch kein effizientes JavaScript schreiben können! :-)


Ich verwende dojo.require Paketverwaltung ( dojo.require und dojo.provide ) und das Klassensystem ( dojo.declare das auch eine einfache Mehrfachvererbung ermöglicht), um alle meine Klassen / Widgets in separate Dateien zu modularisieren. Dosieren Sie nicht nur Ihren Code, sondern lassen Sie auch faules / zeitgerechtes Laden von Klassen / Widgets durchführen.


Lazy Laden Sie den benötigten Code bei Bedarf. Google macht so etwas mit ihrem google.loader


Für JavaScript-Organisation wurde Folgendes verwendet

  1. Ordner für alle Ihre Javascript
  2. Page level javascript erhält eine eigene Datei mit dem gleichen Namen der Seite. ProductDetail.aspx wäre ProductDetail.js
  3. Innerhalb des Javascript-Ordners für Bibliotheksdateien habe ich einen lib-Ordner
  4. Setzen Sie verwandte Bibliotheksfunktionen in einen lib-Ordner, den Sie in Ihrer gesamten Anwendung verwenden möchten.
  5. Ajax ist das einzige Javascript, dass ich außerhalb des Javascript-Verzeichnisses verschiebe und einen eigenen Ordner erhalte. Dann füge ich zwei Unterordner Client und Server hinzu
  6. Der Client-Ordner ruft alle .js-Dateien ab, während der Server-Ordner alle serverseitigen Dateien abruft.

Inspiriert von früheren Posts habe ich eine Kopie von Rakefile und Lieferantenverzeichnissen erstellt, die mit WysiHat (einer RTE, die von WysiHat erwähnt wird) verteilt und einige Änderungen vorgenommen, um Code-Checking mit JSLint und Minification mit YUI Compressor zu integrieren .

Die Idee besteht darin, Ritzel (von WysiHat) zu verwenden, um mehrere JavaScripts zu einer Datei zusammenzuführen, die Syntax der zusammengeführten Datei mit JSLint zu überprüfen und sie vor der Verteilung mit YUI Compressor zu minimieren.

Voraussetzungen

  • java Laufzeit
  • Rubin und Rechen
  • Sie sollten wissen, wie Sie ein JAR in Classpath

Mach jetzt

  1. Lade Rhino herunter und lege das JAR ("js.jar") in deinen Klassenpfad
  2. Lade YUI Compressor herunter und lege das JAR (build / yuicompressor-xyz.jar) in deinen Klassenpfad
  3. Laden Sie WysiHat herunter und kopieren Sie das Verzeichnis "vendor" in das Stammverzeichnis Ihres JavaScript-Projekts
  4. Laden Sie JSLint for Rhino herunter und legen Sie es im Verzeichnis "vendor" ab

Erstellen Sie nun eine Datei namens "Rakefile" im Stammverzeichnis des JavaScript-Projekts und fügen Sie den folgenden Inhalt hinzu:

require 'rake'

ROOT            = File.expand_path(File.dirname(__FILE__))
OUTPUT_MERGED   = "final.js"
OUTPUT_MINIFIED = "final.min.js"

task :default => :check

desc "Merges the JavaScript sources."
task :merge do
  require File.join(ROOT, "vendor", "sprockets")

  environment  = Sprockets::Environment.new(".")
  preprocessor = Sprockets::Preprocessor.new(environment)

  %w(main.js).each do |filename|
    pathname = environment.find(filename)
    preprocessor.require(pathname.source_file)
  end

  output = preprocessor.output_file
  File.open(File.join(ROOT, OUTPUT_MERGED), 'w') { |f| f.write(output) }
end

desc "Check the JavaScript source with JSLint."
task :check => [:merge] do
  jslint_path = File.join(ROOT, "vendor", "jslint.js")

  sh 'java', 'org.mozilla.javascript.tools.shell.Main',
    jslint_path, OUTPUT_MERGED
end

desc "Minifies the JavaScript source."
task :minify => [:merge] do
  sh 'java', 'com.yahoo.platform.yui.compressor.Bootstrap', '-v',
    OUTPUT_MERGED, '-o', OUTPUT_MINIFIED
end

Wenn Sie alles richtig gemacht haben, sollten Sie die folgenden Befehle in Ihrer Konsole verwenden können:

  • rake merge - um verschiedene JavaScript-Dateien in einem zusammenzuführen
  • rake check - um die Syntax Ihres Codes zu überprüfen (dies ist die Standardaufgabe , also können Sie einfach rake eingeben)
  • rake minify - um eine verkleinerte Version Ihres JS-Codes zu erstellen

Beim Zusammenführen der Quelle

Mit dem JavaScript-Preprozessor von Sprockets können Sie andere JavaScript-Dateien einschließen (oder require ). Verwenden Sie die folgende Syntax, um andere Skripts aus der ursprünglichen Datei ("main.js", aber Sie können das in der Rakefile ändern) hinzuzufügen:

(function() {
//= require "subdir/jsfile.js"
//= require "anotherfile.js"

    // some code that depends on included files
    // note that all included files can be in the same private scope
})();

Und dann...

Werfen Sie einen Blick auf Rakefile, das mit WysiHat zur Verfügung gestellt wurde, um den Test der automatisierten Einheit durchzuführen. Gutes Zeug :)

Und jetzt für die Antwort

Dies beantwortet die ursprüngliche Frage nicht sehr gut. Ich weiß, und es tut mir leid, aber ich habe es hier gepostet, weil ich hoffe, dass es für jemand anderen nützlich sein kann, ihr Durcheinander zu organisieren.

Meine Herangehensweise an das Problem ist, so viel objektorientierte Modellierung zu machen und Implementierungen in verschiedene Dateien zu unterteilen. Dann sollten die Handler so kurz wie möglich sein. Das Beispiel mit List singleton ist auch nett.

Und Namespaces ... nun, sie können durch eine tiefere Objektstruktur imitiert werden.

if (typeof org === 'undefined') {
    var org = {};
}

if (!org.hasOwnProperty('example')) {
    org.example = {};
}

org.example.AnotherObject = function () {
    // constructor body
};

Ich bin kein großer Fan von Nachahmungen, aber das kann hilfreich sein, wenn Sie viele Objekte haben, die Sie aus dem globalen Anwendungsbereich entfernen möchten.


Ich konnte das Javascript-Modul-Muster erfolgreich auf eine Ext JS-Anwendung bei meinem vorherigen Job anwenden. Es bot eine einfache Möglichkeit, um schön gekapselten Code zu erstellen.







formatting