Je vais passer en revue quelques choses simples qui pourraient, ou pourraient ne pas, vous aider. Certaines peuvent être évidentes, d'autres extrêmement ésotériques.
Étape 1: Cloisonnez votre code
Séparer votre code en plusieurs unités modulaires est un très bon premier pas. Rassemblez ce qui fonctionne "ensemble" et mettez-les dans leur propre petite unité enfermée. Ne vous inquiétez pas du format pour l'instant, gardez-le en ligne. La structure est un point ultérieur.
Donc, supposez que vous avez une page comme celle-ci :
Il serait logique de compartimenter afin que tous les gestionnaires/déclencheurs d'événements liés à l'en-tête soient là, pour faciliter la maintenance (et ne pas avoir à passer au crible 1000 lignes).
Vous pouvez ensuite utiliser un outil tel que Grunt pour reconstruire votre JS en une unité unique.
Étape 1a: Gestion des dépendances
Utilisez une bibliothèque telle que RequireJS or CommonJS pour implémenter quelque chose appelé AMD. Le Chargement Asynchrone de Modules vous permet d'indiquer explicitement sur quoi votre code dépend, ce qui vous permet ensuite de décharger l'appel à la bibliothèque dans le code. Vous pouvez littéralement dire "Cela a besoin de jQuery" et l'AMD le chargera, et exécutera votre code quand jQuery est disponible.
Cela a aussi un joyau caché : le chargement de la bibliothèque se fera dès que le DOM est prêt, pas avant. Cela n'interrompt plus le chargement de votre page !
Étape 2: Modulaire
Voyez la maquette ? J'ai deux unités publicitaires. Ils auront très probablement des écouteurs d'événements partagés.
Votre tâche dans cette étape est d'identifier les points de répétition dans votre code et d'essayer de tout synthétiser en modules. Les modules, pour l'instant, engloberont tout. Nous découperons les choses au fur et à mesure.
Toute l'idée de cette étape est de passer de l'étape 1 et de supprimer tous les copier-coller, pour les remplacer par des unités qui sont faiblement couplées. Donc, au lieu d'avoir :
ad_unit1.js
$("#au1").click(function() { ... });
ad_unit2.js
$("#au2").click(function() { ... });
J'aurai :
ad_unit.js
:
var AdUnit = function(elem) {
this.element = elem || new jQuery();
}
AdUnit.prototype.bindEvents = function() {
... Les événements vont ici
}
page.js
:
var AUs = new AdUnit($("#au1,#au2"));
AUs.bindEvents();
Cela vous permet de compartimenter entre vos événements et votre markup en plus d'éliminer toute répétition. C'est une étape assez décente et nous étendrons cela plus tard.
Étape 3: Choisissez un framework !
Si vous souhaitez moduler et réduire encore plus les répétitions, il existe de nombreux frameworks géniaux qui implémentent des approches MVC (Modèle - Vue - Contrôleur). Mon préféré est Backbone/Spine, cependant, il y a aussi Angular, Yii, ... La liste est longue.
Un Modèle représente vos données.
Une Vue représente votre mise en page et tous les événements qui y sont associés.
Un Contrôleur représente votre logique métier - en d'autres termes, le contrôleur indique à la page quelles vues charger et quels modèles utiliser.
Ce sera une étape d'apprentissage significative, mais le prix en vaut la peine : il favorise un code propre et modulaire par rapport à du code spaghetti.
Il y a beaucoup d'autres choses que vous pouvez faire, ce ne sont que des directives et des idées.
Changements spécifiques au code
Voici quelques améliorations spécifiques à votre code :
$('.new_layer').click(function(){
dialog("Create new layer","Enter your layer name","_input", {
'OK' : function(){
let reply = $('.dialog_input').val();
if( reply != null && reply != "" ){
let name = "ln_"+reply.split(' ').join('_');
let 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);
}
}
});
});
Ceci est mieux écrit comme :
$("body").on("click",".new_layer", function() {
dialog("Create new layer", "Enter your layer name", "_input", {
OK: function() {
// Il doit y avoir un moyen d'obtenir l'entrée d'ici en utilisant this, s'il s'agit d'une bibliothèque standard. Si vous l'avez écrit vous-même, rendez la valeur accessible en utilisant autre chose qu'un sélecteur de classe (mauvaises performances + portée + problèmes d'instances multiples)
// C'est là que la vue entre en jeu. Au lieu de cloner, liez le rendu dans un prototype JS, et instanciez-le. Cela signifie que vous n'avez à modifier les choses qu'à un seul endroit, vous ne risquez pas de cloner des événements avec, et vous pouvez tester votre Couche seule
let newLayer = new Layer();
newLayer
.setName(name)
.bindToGroup(parent);
}
});
});
Plus tôt dans votre code :
window.Layer = function() {
this.instance = $("
Tout à coup, vous avez un moyen de créer une couche standard de n'importe où dans votre code sans copier-coller. Vous le faites à cinq endroits différents. Je viens de vous épargner cinq copier-coller.
Encore une fois :
// Wrapper de l'ensemble de règles pour les actions
let PageElements = function(ruleSet) {
ruleSet = ruleSet || [];
this.rules = [];
for (let i = 0; i < ruleSet.length; i++) {
if (ruleSet[i].target && ruleSet[i].action) {
this.rules.push(ruleSet[i]);
}
}
}
PageElements.prototype.run = function(elem) {
for (let i = 0; i < this.rules.length; i++) {
this.rules[i].action.apply(elem.find(this.rules.target));
}
}
let 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"));
// Si vous devez ajouter des éléments plus tard, vous pouvez simplement appeler GlobalRules.run(votreNouvelElement);
C'est une manière très puissante d'enregistrer des règles si vous avez des événements qui ne sont pas standard, ou des événements de création. C'est aussi vraiment génial quand combiné avec un système de notification pub/sub et quand lié à un événement que vous déclenchez chaque fois que vous créez des éléments. Liaison événementielle modulaire Fire'n'forget !
0 votes
Si vous souhaitez ajouter backbone.js et require.js, cela nécessitera beaucoup de travail.
0 votes
Je suppose que le chargement paresseux de fichiers séparés n'est pas préférable. Vous devrez probablement interrompre l'exécution pour charger les fichiers externes avant de pouvoir procéder. Une autre solution serait de charger simplement le strict minimum initialement et de continuer à charger le reste en arrière-plan.
0 votes
Requirejs avec backbone pourrait toujours être une bonne option juste pour organiser votre code. Je préfère personnellement utiliser des vues pour lier les écouteurs plutôt que d'utiliser jQuery. Ce n'est pas nécessairement beaucoup de mots. Eh bien, juste un avis.
1 votes
Quelles tâches vous trouvez-vous à faire encore et encore lorsque vous écrivez ceci?
4 votes
Avez-vous visité codereview.stackexchange.com?
0 votes
@MikeSamuel rédiger des auditeurs, beaucoup d'entre eux, cherchant le vrai fichier pour les trouver et les mettre à jour si un bogue se produit, je change un auditeur et d'autres pourraient casser complètement un désordre. C'est pourquoi j'ai fourni ce code pour comprendre ce que j'écris et à quel point cela peut être désordonné pour mettre à jour et organisé.
0 votes
Peut-être organiser votre code avec un espace de noms comme la création d'un objet global comme dans jQuery où l'objet global est
jQuery
et vous trouverezjQuery.events
par exemple qui regroupe tous les événements, les méthodes associées et les objets, etc...4 votes
Apprenez Angular! C'est l'avenir.
2 votes
Votre code ne doit pas être sur un lien externe, il doit être ici. De plus, @codereview est un meilleur endroit pour ce type de questions.
0 votes
Ce n'est pas une réponse à 100% à votre question, mais j'utilise ce site pratiquement à chaque fois que je travaille avec JS. Il contient de nombreux bons motifs que vous pouvez utiliser pour mieux organiser votre code. Je n'ai pas encore trouvé le bon équilibre, mais j'utilise assez souvent le modèle de module. addyosmani.com/resources/essentialjsdesignpatterns/book/…