Ich werde einige einfache Dinge durchgehen, die Ihnen vielleicht helfen oder auch nicht. Einige könnten offensichtlich sein, andere könnten extrem arkan sein.
Schritt 1: Unterteilen Sie Ihren Code
Die Aufteilung Ihres Codes in mehrere modulare Einheiten ist ein sehr guter erster Schritt. Runden Sie ab, was "zusammen" funktioniert, und legen Sie sie in eine eigene kleine Einheit. Mach dir vorerst keine Sorgen um das Format, halte es inline. Die Struktur ist ein späterer Punkt.
Angenommen, Sie haben eine Seite wie diese:
Es wäre sinnvoll, eine Unterteilung vorzunehmen, damit alle Header-bezogenen Ereignishandler / -binder vorhanden sind, um die Wartung zu vereinfachen (und nicht 1000 Zeilen durchsuchen zu müssen).
Sie können dann ein Tool wie Grunt verwenden, um Ihr JS wieder zu einer einzigen Einheit zusammenzusetzen.
Schritt 1a: Abhängigkeitsmanagement
Verwenden Sie eine Bibliothek wie RequireJS oder CommonJS, um etwas namens AMD zu implementieren . Durch das Laden des asynchronen Moduls können Sie explizit angeben, wovon Ihr Code abhängt, und dann den Bibliotheksaufruf in den Code auslagern. Sie können einfach wörtlich "Dies benötigt jQuery" sagen und der AMD lädt es und führt Ihren Code aus, wenn jQuery verfügbar ist .
Dies hat auch ein verstecktes Juwel: Das Laden der Bibliothek erfolgt in der Sekunde, in der das DOM bereit ist, nicht vorher. Dadurch wird das Laden Ihrer Seite nicht mehr angehalten!
Schritt 2: Modularisieren
Sehen Sie das Drahtmodell? Ich habe zwei Anzeigenblöcke. Sie werden höchstwahrscheinlich gemeinsame Ereignis-Listener haben.
Ihre Aufgabe in diesem Schritt ist es, die Wiederholungspunkte in Ihrem Code zu identifizieren und zu versuchen, all dies zu Modulen zusammenzufassen . Module werden im Moment alles umfassen. Wir werden Sachen aufteilen, wenn wir weitergehen.
Die ganze Idee dieses Schritts besteht darin, von Schritt 1 aus alle Kopiernudeln zu löschen, um sie durch lose gekoppelte Einheiten zu ersetzen. Also, anstatt zu haben:
ad_unit1.js
$("#au1").click(function() { ... });
ad_unit2.js
$("#au2").click(function() { ... });
Ich werde haben:
ad_unit.js
::
var AdUnit = function(elem) {
this.element = elem || new jQuery();
}
AdUnit.prototype.bindEvents = function() {
... Events go here
}
page.js
::
var AUs = new AdUnit($("#au1,#au2"));
AUs.bindEvents();
Dies ermöglicht es Ihnen, zwischen Ihren Ereignissen und Ihrem Markup zu unterteilen und Wiederholungen zu vermeiden. Dies ist ein ziemlich anständiger Schritt und wir werden ihn später weiter ausbauen.
Schritt 3: Wählen Sie ein Framework!
Wenn Sie Wiederholungen noch weiter modularisieren und reduzieren möchten, gibt es eine Reihe großartiger Frameworks, die MVC-Ansätze (Model - View - Controller) implementieren. Mein Favorit ist Backbone / Spine, aber es gibt auch Angular, Yii, ... Die Liste geht weiter.
Ein Modell repräsentiert Ihre Daten.
Eine Ansicht repräsentiert Ihr Markup und alle damit verbundenen Ereignisse
Ein Controller repräsentiert Ihre Geschäftslogik. Mit anderen Worten, der Controller teilt der Seite mit, welche Ansichten geladen und welche Modelle verwendet werden sollen.
Dies wird ein bedeutender Lernschritt sein, aber der Preis ist es wert: Er bevorzugt sauberen, modularen Code gegenüber Spaghetti.
Es gibt viele andere Dinge, die Sie tun können, das sind nur Richtlinien und Ideen.
Code-spezifische Änderungen
Hier sind einige spezifische Verbesserungen an Ihrem Code:
$('.new_layer').click(function(){
dialog("Create new layer","Enter your layer name","_input", {
'OK' : function(){
var reply = $('.dialog_input').val();
if( reply != null && reply != "" ){
var name = "ln_"+reply.split(' ').join('_');
var parent = "";
if(selected_folder != "" ){
parent = selected_folder+" .content";
}
$R.find(".layer").clone()
.addClass(name).html(reply)
.appendTo("#layer_groups "+parent);
$R.find(".layers_group").clone()
.addClass(name).appendTo('#canvas '+selected_folder);
}
}
});
});
Dies ist besser geschrieben als:
$("body").on("click",".new_layer", function() {
dialog("Create new layer", "Enter your layer name", "_input", {
OK: function() {
// There must be a way to get the input from here using this, if it is a standard library. If you wrote your own, make the value retrievable using something other than a class selector (horrible performance + scoping +multiple instance issues)
// This is where the view comes into play. Instead of cloning, bind the rendering into a JS prototype, and instantiate it. It means that you only have to modify stuff in one place, you don't risk cloning events with it, and you can test your Layer stand-alone
var newLayer = new Layer();
newLayer
.setName(name)
.bindToGroup(parent);
}
});
});
Früher in Ihrem Code:
window.Layer = function() {
this.instance = $("<div>");
// Markup generated here
};
window.Layer.prototype = {
setName: function(newName) {
},
bindToGroup: function(parentNode) {
}
}
Plötzlich haben Sie die Möglichkeit, von überall in Ihrem Code eine Standardebene zu erstellen, ohne sie einzufügen. Du machst das an fünf verschiedenen Orten. Ich habe dir gerade fünf Kopierpasten gespeichert.
Einer noch:
// Regelsatz-Wrapper für Aktionen
var PageElements = function(ruleSet) {
ruleSet = ruleSet || [];
this.rules = [];
for (var i = 0; i < ruleSet.length; i++) {
if (ruleSet[i].target && ruleSet[i].action) {
this.rules.push(ruleSet[i]);
}
}
}
PageElements.prototype.run = function(elem) {
for (var i = 0; i < this.rules.length; i++) {
this.rules[i].action.apply(elem.find(this.rules.target));
}
}
var GlobalRules = new PageElements([
{
"target": ".draggable",
"action": function() { this.draggable({
cancel: "div#scrolling, .content",
containment: "document"
});
}
},
{
"target" :".resizable",
"action": function() {
this.resizable({
handles: "all",
zIndex: 0,
containment: "document"
});
}
}
]);
GlobalRules.run($("body"));
// If you need to add elements later on, you can just call GlobalRules.run(yourNewElement);
Dies ist eine sehr wirksame Methode, um Regeln zu registrieren, wenn Sie Ereignisse haben, die nicht Standard sind, oder Erstellungsereignisse. Dies ist auch in Kombination mit einem Pub / Sub-Benachrichtigungssystem und wenn es an ein Ereignis gebunden ist, das Sie auslösen, wenn Sie Elemente erstellen, ein echter Kick-Ass. Fire'n'forget modulare Ereignisbindung!