removeattribute removeattr disabled attribute javascript jquery design-patterns backbone.js requirejs

removeattr - La mejor forma de organizar el código jQuery/JavaScript(2013)



removeattr disabled (8)

El problema

Esta respuesta ha sido respondida anteriormente pero es antigua y no está actualizada. Tengo más de 2000 líneas de código en un solo archivo, y como todos sabemos, esta es una mala práctica, especialmente cuando busco un código o agrego nuevas características. Quiero organizar mejor mi código, por ahora y para el futuro.

Debo mencionar que estoy construyendo una herramienta (no un sitio web simple) con muchos botones, elementos de IU, arrastrar, soltar, oyentes / manipuladores de acción y funciones en el ámbito global donde varios oyentes pueden usar la misma función.

Código de ejemplo

$(''#button1'').on(''click'', function(e){ // Determined action. update_html(); }); ... // Around 75 more of this function update_html(){ .... } ...

Más código de ejemplo

Conclusión

Realmente necesito organizar este código para un mejor uso y no repetirme y ser capaz de agregar nuevas funciones y actualizar las viejas. Trabajaré solo en esto. Algunos selectores pueden tener 100 líneas de código, otras son 1. He buscado un poco en require.js y me pareció un poco repetitivo, y de hecho estoy escribiendo más código del necesario. Estoy abierto a cualquier posible solución que se ajuste a este criterio y el enlace a recursos / ejemplos son siempre un plus.

Gracias.


Aquí hay una manera simple de dividir su base de código actual en varios archivos, usando require.js. Le mostraré cómo dividir su código en dos archivos. Agregar más archivos será sencillo después de eso.

Paso 1) En la parte superior de tu código, crea un objeto de la aplicación (o el nombre que prefieras, como MyGame):

var App = {}

Paso 2) Convierta todas sus variables y funciones de nivel superior para que pertenezcan al objeto de la aplicación.

En lugar de:

var selected_layer = "";

Usted quiere:

App.selected_layer = "";

En lugar de:

function getModified(){ ... }

Usted quiere:

App.getModified = function() { }

Tenga en cuenta que en este punto su código no funcionará hasta que termine el próximo paso.

Paso 3) Convierta todas las variables globales y las referencias de funciones para pasar por la aplicación.

Cambiar cosas como:

selected_layer = "."+classes[1];

a:

App.selected_layer = "."+classes[1];

y:

getModified()

a:

App.GetModified()

Paso 4) Pruebe su código en esta etapa; todo debería funcionar. Probablemente, al principio, obtendrá algunos errores porque se olvidó de algo, así que corríjalos antes de continuar.

Paso 5) Configurar requirejs. Supongo que tiene una página web, servida desde un servidor web, cuyo código está en:

www/page.html

y jquery en

www/js/jquery.js

Si estas rutas no son exactamente así, lo siguiente no funcionará y tendrás que modificar las rutas.

Descargue requirejs y coloque require.js en su directorio www/js .

en su page.html , elimine todas las etiquetas de script e inserte una etiqueta de script como:

<script data-main="js/main" src="js/require.js"></script>

crea www/js/main.js con contenido:

require.config({ "shim": { ''jquery'': { exports: ''$'' } } }) require([''jquery'', ''app'']);

luego coloque todo el código que acaba de arreglar en los pasos 1-3 (cuya única variable global debería ser la aplicación) en:

www/js/app.js

En la parte superior de ese archivo, escriba:

require([''jquery''], function($) {

En la parte inferior poner:

})

Luego cargue page.html en su navegador. Tu aplicación debería funcionar!

Paso 6) Crea otro archivo

Aquí es donde su trabajo da sus frutos, puede hacerlo una y otra vez.

Extraiga algún código de www/js/app.js que haga referencia a $ y a la aplicación.

p.ej

$(''a'').click(function() { App.foo() }

Ponlo en www/js/foo.js

En la parte superior de ese archivo, escriba:

require([''jquery'', ''app''], function($, App) {

En la parte inferior poner:

})

A continuación, cambie la última línea de www / js / main.js a:

require([''jquery'', ''app'', ''foo'']);

¡Eso es! ¡Haga esto cada vez que quiera poner el código en su propio archivo!


Categoriza tu código. Este método me está ayudando mucho y funciona con cualquier framework js:

(function(){//HEADER: menu //your code for your header })(); (function(){//HEADER: location bar //your code for your location })(); (function(){//FOOTER //your code for your footer })(); (function(){//PANEL: interactive links. e.g: var crr = null; $(''::section.panel a'').addEvent(''click'', function(E){ if ( crr) { crr.hide(); } crr = this.show(); }); })();

En su editor preferido (el mejor es Komodo Edit) puede doblar al colapsar todas las entradas y verá solo los títulos:

(function(){//HEADER: menu_____________________________________ (function(){//HEADER: location bar_____________________________ (function(){//FOOTER___________________________________________ (function(){//PANEL: interactive links. e.g:___________________


Para sus preguntas y comentarios, supongo que no está dispuesto a portar su código a un framework como Backbone, o usar una biblioteca de carga como Require. Solo desea una forma mejor de organizar el código que ya tiene, de la manera más simple posible.

Entiendo que es molesto desplazarse a través de más de 2000 líneas de código para encontrar la sección en la que desea trabajar. La solución es dividir el código en diferentes archivos, uno para cada funcionalidad. Por ejemplo, sidebar.js , sidebar.js , etc. Luego puedes unirlos para producción usando Grunt, junto con Usemin puedes tener algo como esto:

En tu html:

<!-- build:js scripts/app.js --> <script src="scripts/sidebar.js"></script> <script src="scripts/canvas.js"></script> <!-- endbuild -->

En tu Gruntfile:

useminPrepare: { html: ''app/index.html'', options: { dest: ''dist'' } }, usemin: { html: [''dist/{,*/}*.html''], css: [''dist/styles/{,*/}*.css''], options: { dirs: [''dist''] } }

Si quieres usar Yeoman, te dará un código repetitivo para todo esto.

Luego, para cada archivo en sí, debe asegurarse de seguir las mejores prácticas y que todo el código y las variables estén todos en ese archivo y no dependan de otros archivos. Esto no significa que no pueda llamar funciones de un archivo a otro, el punto es tener variables y funciones encapsuladas. Algo similar al espacio de nombres. Asumiré que no quieres que todo tu código sea orientado a objetos, pero si no te importa refactorizar un poco, te recomiendo agregar algo equivalente con lo que se llama un patrón de Módulo. Se ve algo como esto:

sidebar.js

var Sidebar = (function(){ // functions and vars here are private var init = function(){ $("#sidebar #sortable").sortable({ forceHelperSize: true, forcePlaceholderSize: true, revert: true, revert: 150, placeholder: "highlight panel", axis: "y", tolerance: "pointer", cancel: ".content" }).disableSelection(); } return { // here your can put your "public" functions init : init } })();

Entonces puedes cargar este bit de código así:

$(document).ready(function(){ Sidebar.init(); ...

Esto le permitirá tener un código mucho más fácil de mantener sin tener que reescribir demasiado el código.


Repasaremos algunas cosas simples que pueden, o no, ayudarte. Algunos podrían ser obvios, algunos podrían ser extremadamente arcanos.

Paso 1: Compartimentalice su código

Separar tu código en múltiples unidades modulares es un muy buen primer paso. Reúna lo que funciona "en conjunto" y colóquelos en su propia unidad encajonada. no se preocupe por el formato por ahora, manténgalo en línea. La estructura es un punto posterior.

Entonces, supongamos que tienes una página como esta:

Tendría sentido dividir en compartimientos para que todos los manejadores / encuadernadores de eventos relacionados con el encabezado estén ahí, para facilitar el mantenimiento (y no tener que pasar por 1000 líneas).

Luego puede usar una herramienta como Grunt para volver a construir su JS en una sola unidad.

Paso 1a: gestión de la dependencia

Use una biblioteca como RequireJS o CommonJS para implementar algo llamado AMD . La carga de módulos asíncronos le permite indicar explícitamente de qué depende su código, lo que le permite descargar las llamadas a la biblioteca al código. Simplemente puede decir "Esto necesita jQuery" y AMD lo cargará y ejecutará su código cuando jQuery esté disponible .

Esto también tiene una gema oculta: la carga de la biblioteca se realizará en el momento en que el DOM esté listo, no antes. ¡Esto ya no detiene la carga de tu página!

Paso 2: Modularizar

¿Ves la estructura alámbrica? Tengo dos bloques de anuncios. Lo más probable es que hayan compartido oyentes de eventos.

Su tarea en este paso es identificar los puntos de repetición en su código y tratar de sintetizar todo esto en módulos . Los módulos, ahora mismo, abarcarán todo. Dividiremos las cosas a medida que avanzamos.

La idea de este paso es ir desde el paso 1 y eliminar todas las pastas de copia, para reemplazarlas con unidades que están ligeramente acopladas. Entonces, en lugar de tener:

ad_unit1.js

$("#au1").click(function() { ... });

ad_unit2.js

$("#au2").click(function() { ... });

Tendré:

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

Lo que le permite dividir en compartimientos entre sus eventos y su marcado, además de deshacerse de la repetición. Este es un paso bastante decente y ampliaremos esto más adelante.

Paso 3: ¡elige un marco!

Si desea modularizar y reducir las repeticiones aún más, hay una gran cantidad de impresionantes marcos que implementan los enfoques MVC (Modelo - Vista - Controlador). Mi favorito es Backbone / Spine, sin embargo, también hay Angular, Yii, ... La lista continúa.

Un modelo representa tus datos.

Una vista representa su margen de beneficio y todos los eventos asociados a ella

Un controlador representa la lógica de su negocio; en otras palabras, el controlador le dice a la página qué vistas cargar y qué modelos usar.

Este será un paso importante de aprendizaje, pero el premio vale la pena: favorece el código limpio y modular sobre los espaguetis.

Hay muchas otras cosas que puede hacer, esas son solo pautas e ideas.

Cambios específicos del código

Aquí hay algunas mejoras específicas a su código:

$(''.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); } } }); });

Esto está mejor escrito como:

$("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); } }); });

Anteriormente en tu código:

window.Layer = function() { this.instance = $("<div>"); // Markup generated here }; window.Layer.prototype = { setName: function(newName) { }, bindToGroup: function(parentNode) { } }

De repente, tiene una manera de crear una capa estándar desde cualquier lugar en su código sin copiar pegar. Estás haciendo esto en cinco lugares diferentes. Acabo de salvarte cinco copias.

Uno mas:

// Contenedor de conjuntos de reglas para acciones

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

Esta es una forma muy potente de registrar reglas si tiene eventos que no son estándar o eventos de creación. Esto también es una verdadera patada cuando se combina con un sistema de notificación de pub / sub y cuando está vinculado a un evento que se activa cada vez que se crean elementos. Fire''n''getget binding de eventos modulares!


Sugiero que uses algo como Backbone. Backbone es una biblioteca de JavaScript compatible con RESTFUL. Ik hace que su código sea más limpio y legible, y es poderoso cuando se usa junto con requirejs.

Backbone

RequireJS

Backbone no es una biblioteca real. Está destinado a dar estructura a su código de JavaScript. Puede incluir otras bibliotecas como jquery, jquery-ui, google-maps, etc. Backbone es, en mi opinión, el enfoque javascript más cercano a estructuras orientadas a objetos y Model View Controller.

También con respecto a su flujo de trabajo ... Si crea sus aplicaciones en PHP use la biblioteca Laravel. Funcionará sin problemas con Backbone cuando se usa con el principio RESTfull. Debajo del enlace a Laravel Framework y un tutorial sobre la creación de API RESTfull:

http://maxoffsky.com/code-blog/building-restful-api-in-laravel-start-here/

http://laravel.com/

A continuación hay un tutorial de nettuts. Nettuts tiene muchos tutoriales de alta calidad:

http://net.tutsplus.com/tutorials/javascript-ajax/understanding-backbone-js-and-the-server/


Tal vez es hora de que empieces a implementar un flujo de trabajo de desarrollo completo usando herramientas como yeoman http://yeoman.io/ . Esto ayudará a controlar todas sus dependencias, el proceso de compilación y, si lo desea, las pruebas automatizadas. Es mucho trabajo para empezar, pero una vez implementado hará que los cambios futuros sean mucho más fáciles.


Utilice javascript MVC Framework para organizar el código de JavaScript de forma estándar.

Los mejores frameworks JavaScript MVC disponibles son:

La selección de un marco JavaScript MVC requería tantos factores para tener en cuenta. Lea el siguiente artículo de comparación que lo ayudará a seleccionar el mejor marco según los factores importantes para su proyecto: http://sporto.github.io/blog/2013/04/12/comparison-angular-backbone-can-ember/

También puede usar RequireJS con el marco para admitir el archivo Asynchrounous js y la carga del módulo.
Consulte lo siguiente para comenzar a cargar el módulo JS:
http://www.sitepoint.com/understanding-requirejs-for-effective-javascript-module-loading/


Yo sugeriría:

  1. patrón de editor / suscriptor para la gestión de eventos.
  2. orientación a objetos
  3. espacio de nombres

En su caso Jessica, divida la interfaz en páginas o pantallas. Las páginas o pantallas pueden ser objetos y extendidas desde algunas clases principales. Administre las interacciones entre páginas con una clase de PageManager.