Acoplamiento ajustado entre Javascript, HTML y CSS: ¿un enfoque más moderno?

29

Es muy común ver Javascript vinculado a ciertos selectores para buscar elementos, almacenar datos y escuchar eventos. También es común ver estos mismos selectores utilizados para el estilo.

jQuery (y su motor selector Sizzle) admiten y promueven esto al hacer referencia a elementos con sintaxis de tipo CSS. Como tal, esta técnica es particularmente difícil de "desaprender" (o refactorizar) al construir proyectos.

He llegado a comprender que esto es el resultado de la historia del desarrollo de HTML y Javascript, y que los navegadores se han creado para consumir / analizar / generar de manera eficiente este tipo de acoplamiento. Pero a medida que los sitios web se vuelven cada vez más complejos, esta realidad puede introducir dificultades para organizar y mantener estas capas separadas.

Mi pregunta es: ¿puede y debe evitarse esto en los sitios web modernos?

Si soy nuevo en el desarrollo front-end y deseo aprender las cosas 'de la manera correcta', ¿vale la pena aprender a desacoplar y evitar tales dependencias desde el principio? ¿Esto significa evitar jQuery a favor de una biblioteca que promueva una estructura más desacoplada?

Stuart Kershaw
fuente
1
¿Cómo funcionaría tal cosa? ¿Cómo, por ejemplo, deshabilita un control en una página sin tocar ese control de alguna manera, o sin tener conocimiento de él? (esta es mi pequeña forma de decir que debe ser más específico sobre lo que quiere decir con desacoplamiento, idealmente con algunos ejemplos, incluso si son artificiales).
Robert Harvey
2
Lo más importante cuando se habla de desacoplar html, css y js es usar selectores de clase en lugar de cualquier otro, este es el concepto central de metodologías como oocss y BEM.
angvillar
Aprenda React o componentes web, y ya no tendrá que molestarse con los selectores en JS.
Andy

Respuestas:

35

No hay forma de evitar eso. Están acoplados porque interactúan entre sí. Si su javascript tiene la intención de hacer algún tipo de manipulación DOM, entonces necesita una forma de hacer referencia al DOM.

Hay varias convenciones para ello.

La API DOM de nivel 2 proporciona los métodos getElementById, getElementByTagName y getElementsByName. Hasta el día de hoy, estos son los caballos de batalla de cualquier tipo de recorrido DOM. Todos los demás selectores jQuery más sofisticados se resuelven en una combinación de estos eventualmente, y / o un recorrido directo hacia arriba de cada nodo DOM (esta era la forma de obtener getByClassName).

No hay otro atajo. Javascript necesita saber qué hacer y dónde. Por lo general, si un elemento tiene una identificación o clase que solo es relevante en las secuencias de comandos, muchas personas lo prefijarán con js-algún otro indicador obvio.

Otra convención más nueva es la selección de atributos de datos.

<ul data-myapp-sortable="true">

jQuery('[data-myapp-sortable]').makeSortable();

El atributo de datos generalmente se usa con fines de secuencias de comandos y la selección que usa tiene algún sentido. El inconveniente es que esto es más lento que usar getElementById ().

Otro enfoque es el utilizado por angularJS, que crea un modelo de vista. En esta convención, cualquier tipo de funcionalidad de scripting se especifica mediante atributos especialmente designados como ng-disabled ng-hrefy muchos más. No agrega selectores en su javascript. El documento HTML se convierte en la principal autoridad sobre qué está programado y cómo, y el JavaScript funciona de manera abstracta. Es un buen enfoque, pero obviamente con una curva de aprendizaje más alta que los métodos anteriores. Y nuevamente, el rendimiento tiene que ser considerado.

Pero nunca piense que puede escribir HTML y javascript interactivos, y de alguna manera ambas partes no se conocen entre sí. Se trata más acerca de cómo puede limitar las referencias a las dependencias.

mastaBlasta
fuente
2
Respuesta brillante, +1. Aunque solo sea por mencionar los atributos de datos como un mecanismo para evitar el acoplamiento estrecho
Fergus en Londres el
3
Los atributos de datos no son una panacea. Son muy populares en estos días y la gente está poniendo todo menos el fregadero en ellos. Muchos frameworks (por ejemplo, jQuery UI) los usan ampliamente. Debes ser muy estricto con el espacio de nombres y otras convenciones para evitar problemas. Ayudan a desacoplar HTML de JS, pero no necesariamente facilitan la depuración.
mastaBlasta
Nunca entendí por qué era necesario reinventar el uso de clases, identificadores y atributos de datos como ganchos y banderas de estado. Todo lo que Angular ha logrado en ese sentido es una reducción en el rendimiento y reemplazó la convención ampliamente conocida / entendida por una nueva que requiere que uno entienda cómo hacerlo "a la manera Angular", inventando sus propios atributos y etiquetas. No hay una gran curva de aprendizaje allí. Es simplemente más lento, contrario a la convención perfectamente razonable y comúnmente conocida y a una OMI completamente innecesaria.
Erik Reppen
9

Si estás dispuesto a renunciar a la interactividad que obtienes, puedes evitar Javascript por completo. Los marcos como ASP.NET MVC son muy buenos para servir páginas que solo contienen HTML, CSS y un botón ENVIAR.

OKAY. Tal vez eso sea un poco extremo.

El desacoplamiento en una aplicación web ya ocurre en muchos niveles. Las aplicaciones REST le permiten definir su aplicación en términos de "recursos web" asociados con una URL. Ver modelos le permite presentar datos a la interfaz de usuario que está desacoplada del modelo de dominio, pero tiene la forma que necesita para mostrarla correctamente. Las capas de servicio permiten intercambiar una IU por otra, y así sucesivamente.

Históricamente, siempre ha habido una compensación entre interactividad y acoplamiento. Cuanto más interactiva sea su página web, más estrecha será la aplicación. Pero la lógica de interactividad en la página web se limita a la página web misma; cualquier acoplamiento con el servidor se realizará a través de POST o AJAX. Por lo tanto, no estoy seguro de que deba preocuparse demasiado por el acoplamiento a nivel Javascript, aparte de prestar atención a la forma en que se pasan los paquetes de datos entre el navegador y el servidor.

El enfoque más "moderno" (es decir, el sabor de la semana) es probablemente aplicaciones de SPA .

Robert Harvey
fuente
No me suena extremo. Muchos sitios que hacen un uso extensivo de JavaScript, hasta el punto de que no se pueden usar sin él, en realidad no lo necesitan. Ojalá sus desarrolladores tuvieran más pistas ...
Michael Hampton
5

Martin Fowler describe un enfoque para esto como el DOM segregado , donde separa su JavaScript DOM de su JavaScript de lógica de página.

Application Logic <----> DOM Manipulation <----> DOM / HTML
Rory Hunter
fuente
1
+1 Estoy totalmente de acuerdo con segregar la lógica DOM <--> de JavaScript. Realmente no me gustan los atributos de datos, ya que estos no son pertinentes para el DOM sino para una herramienta externa. Siento que un enfoque más limpio es tener algún tipo de mapeo. Sí, esto puede significar que tiene un archivo con referencias a dos aspectos (por ejemplo, funciones JS y elementos DOM) en lugar de, por ejemplo, el DOM que contiene algunas referencias que el JS recoge (que podría describirse como 'aspecto único '). Sin embargo, si se hace cuidadosamente, esto puede ser muy fácil de mantener, reutilizar y ofrecer una mejor separación de las preocupaciones que los atributos de los datos.
awj
2

No, no se debe evitar el uso de selectores de clase, elemento e ID del lado del cliente. La sintaxis se usa porque los selectores de CSS son un lenguaje de dominio muy maduro y bien establecido, y tener un diseño común hace que sea mucho más fácil compartir un modelo lógico común de una página entre el programa y el diseño, lo cual es algo muy, muy bueno.

Si bien es posible utilizar incorrectamente esta sintaxis y crear una aplicación terrible e imposible de mantener, es posible independientemente de su idioma o conjunto de herramientas.

DougM
fuente
2
De hecho, recomiendo no usar selectores de clase, elemento e ID para muchas cosas, y en su lugar me enfoco en usar [data-*]selectores de atributos personalizados , que pueden usarse de maneras muy poderosas.
zzzzBov
2
Mal consejo en mi mente, especialmente cuando se trata de escribir JS modular / reutilizable que no debe suponerse en los selectores. Los atributos de datos son una mejor idea para estos escenarios.
Fergus en Londres
3
@zzzzBov: sé que es una microoptimización, pero las búsquedas de ID y de clase son mucho más rápidas que las búsquedas de atributos de datos. Pero sí, me gusta la idea de usar diferentes conjuntos de atributos para manejar diferentes preocupaciones.
Jimmy Breck-McKye
0

Alguien necesita construir una interfaz de administrador de ruta jQuery para una indirección y una capa de caché para dom.

pathMgr.register(name,selector [,isDynamic=false]);
pathMgr.get(name [,refresh]);

Luego,

String.prototype.reg([isDynamic=false]);
String.prototype.get(name [,refresh]);

Asi que,

// at init....
var pathMgr=new PathMgr();
'sidebar-links #sidebar a'.reg();// new registery of selector '#sidebar a' under name 'sidebar-links'
// more, more


// in code
'sidebar-links'.get().css(etc...);
//or
'sidebar-links'.addStyleRule({});
marca
fuente