Usando el prototipo de JavaScript con MVC

En este artículo, revisaremos el proceso de uso de JavaScript, desde una perspectiva basada en MVC, para manipular el DOM. Más específicamente, diseñaremos nuestros objetos JavaScript, sus propiedades y métodos, y sus instancias paralelas al comportamiento previsto de nuestras Vistas (lo que el usuario ve).


Considere sus vistas como objetos, no como páginas

En cualquier punto del desarrollo de una página web, estamos usando un lenguaje que naturalmente promueve el desarrollo basado en clases o el desarrollo basado en objetos. En lenguajes fuertemente tipados como Java y C #, usualmente estamos escribiendo nuestras vistas en clases, dándoles el estado, el alcance y el contexto. Cuando trabajamos con lenguajes como PHP o motores de visualización más nuevos, como Razor para ASP.NET, nuestras vistas pueden simplemente ser marcas (HTML / CSS) combinadas con plantillas. Sin embargo, esto no significa que tengamos que cambiar nuestra percepción sobre cómo se comporta la vista como su propia entidad con estado..

Dentro de Views, estamos trabajando principalmente con HTML, que consiste en elementos anidados; estos elementos tienen atributos que describen cuál es su propósito semántico o cómo aparecen cuando se procesan. Luego, estos elementos tienen elementos secundarios o primarios que heredan / proveen en cascada (a través de CSS) y comportamientos de bloque / en línea. Estos elementos pueden verse naturalmente desde una perspectiva OOP (Programación Orientada a Objetos). Considere, por ejemplo, el siguiente marcado:

 div.container border: 1px solid # 333; relleno: 5px; color rojo; 
 

Sobre nuestra compañía

Resultado:

Como puede ver arriba, el encabezado heredó su propiedad de color de fuente de su contenedor primario a través del comportamiento CSS de la cascada. Este comportamiento es bastante similar al concepto de herencia en OOP. También podemos ver que el encabezado es un elemento secundario del contenedor, que hereda ciertas propiedades, según el comportamiento del elemento. Cuando vemos nuestros elementos desde esta perspectiva, tenemos una mejor definición de lo que pretendemos hacer con nuestros elementos de vista y podemos encapsular mejor los estilos y la funcionalidad..

Dentro de una vista, tendremos marcado. Sin embargo, este marcado puede tener vistas parciales anidadas como barras laterales, un encabezado, un pie de página, un carril derecho (o izquierdo) y una o más secciones de contenido. Todas estas vistas parciales deben considerarse como su propia entidad, capaz de tener su propio estado, contexto y alcance..

"Cuando concibe sus vistas y vistas parciales como objetos, hace que escribir su código del lado del cliente sea mucho más fácil".


Traducir este concepto a tus estilos y scripts

Muchos desarrolladores tienden a escribir JavaScript desde un punto de vista de procedimiento o funcional, y a menudo se niegan a considerar las tendencias naturales que se ofrecen en los enfoques de desarrollo basados ​​en vistas y en la creación de instancias paralelas (creando una nueva instancia de la vista cuando creamos una nueva instancia de un JavaScript objeto correspondiente a esa vista) cuando se trabaja en MVC Frameworks. A menudo es el caso que me encuentro con archivos JavaScript que son solo un método después de otro. Aunque este comportamiento funciona, y es común, no es muy eficiente para el mantenimiento, la depuración o la extensión del código actual o futuro cuando se trabaja de forma extensa con vistas..

Para alejarse de este hábito y comenzar a escribir un mejor código de comportamiento, cuando comience a diseñar las secuencias de comandos y los estilos de su Vista, siga estas reglas generales:

Reglas de oro del desarrollo de JavaScript basado en vistas

  • Cada vista que se representa desde una acción en un controlador debe tener su propio objeto JavaScript.
  • Cada vista parcial que se carga dentro de una vista debe tener su propio objeto JavaScript.
  • Nombre sus objetos igual que sus vistas (o vistas parciales). Esto tendrá más sentido para usted y para todos los demás que toquen su código..
  • Utilice el caso de Pascal para todos los objetos (es decir, Acerca de, Barra lateral, etc.). Sus vistas ya deberían estarlo, ¿por qué no hacer lo mismo con sus objetos JavaScript??
  • Todas las constantes de estos objetos deben almacenarse en el constructor. Esto significa que si su vista tiene propiedades que se utilizarán en varios métodos, todos estos métodos pueden acceder a estas propiedades.
  • Todos los métodos que se llamarán en una vista (o vista parcial) deben estar vinculados al prototipo del objeto que corresponde a esa vista.
  • Todos los enlaces de eventos para la vista (o vista parcial) deben estar contenidos dentro de su propio método de enlace de eventos, que se coloca en el prototipo.

Considera el siguiente diagrama:

Por lo general, creo estilos y secuencias de comandos específicos para cada vista y luego tomo lo que necesito de las hojas de estilo principales y las bibliotecas de secuencias de comandos que he creado y que se usarían en muchas vistas. Esto también reduce la cantidad de código que se utiliza.


Creación de objetos basados ​​en vistas

En este artículo, presentaremos la estructura de la página Acerca de nosotros en un sitio basado en MVC. Para comenzar, crearemos la estructura como se muestra arriba en el diagrama anterior. A partir de ahí, crearemos un objeto Acerca de, y comenzaremos a agregar métodos al prototipo. Primero, considera el siguiente diseño visual:

Este es un diseño muy lógico y comúnmente utilizado para una página web. Podemos segmentar nuestra página en objetos visuales separados. Para cada una de estas vistas, podemos crear un objeto lógico que se corresponderá con él. Generalmente omito la información repetitiva en el nombre de archivo o el nombre de clase que usa MVC para determinar el URI de la ruta y, en cambio, me quedo con algo que es fácil de mantener consistente.

Para las vistas de página, generalmente llamo a mis objetos de JavaScript por el nombre de la vista. Aquí hay un ejemplo de mi objeto AboutView:

 // Ver nombre de archivo: AboutView.cs (.NET MVC 1.0), About.cshtml (.NET MVC 3.0), o AboutView.php (PHP) var About = function (pageTitle) this.pageTitle = pageTitle; // eventos vinculantes tan pronto como el objeto es instanciado this.bindEvents (); ;

En el ejemplo anterior, creamos un objeto JavaScript en el formato de función, lo que le da la capacidad de servir como un constructor de objetos para todos los métodos a los que se llama para la vista de. Al elegir este formato, podemos instanciar una nueva instancia de esta, tal como lo hacemos con nuestra vista Server-Side (diciendo nuevo AboutView ();). Desde aquí, podemos asignar propiedades y métodos a este objeto. Para asignar métodos a este objeto, necesitaremos acceso al prototipo del objeto..


El prototipo de JavaScript es tu amigo

Los desarrolladores a menudo se ven frustrados por la elusividad (y la ambigüedad) del prototipo de objeto de JavaScript.

Los desarrolladores a menudo se ven frustrados por la elusividad (y la ambigüedad) del prototipo de objeto de JavaScript. Para muchos, puede ser confuso usar y entender y agrega otra dimensión a la codificación. A medida que JavaScript se vuelve más impulsado por eventos con los conceptos de HTML5, AJAX y web 2.0, JavaScript tiende a inclinarse naturalmente hacia el desarrollo de procedimientos que es fácil de desarrollar pero difícil de mantener, escalar y replicar..

Piensa en la palabra Prototipo como un nombre inapropiado por ahora. Cuando pienso Prototipo, Pienso en un "borrador" o en una base para la herencia, pero este no es exactamente el caso.

"En realidad, la mejor perspectiva para Prototype sería el puntero del objeto en la memoria".

Cuando creamos un objeto, instanciamos una nueva instancia de él. Cuando hacemos eso, creamos un lugar en la memoria al que se puede hacer referencia al objeto (recuerde, los objetos en JavaScript son tipos de referencia, tipos no primitivos; crear otra variable igual a ese objeto y luego cambiar sus valores cambiará el objeto original en el puntero). Cuando creamos un objeto, creamos una instancia de él y luego modificamos su "puntero" o Prototipo, agregamos campos y métodos a ese objeto en la memoria directamente (obviamente queremos agregar todas estas cosas antes de la creación de instancias).

Aquí hay un ejemplo de crear métodos en el Acerca de prototipo del objeto:

 var Acerca de = function (pageTitle) this.pageTitle = pageTitle; // eventos vinculantes tan pronto como el objeto es instanciado this.bindEvents (); ; var About.prototype.bindEvents = function () // Contexto actual: 'this' es el objeto About // Coloque todos sus enlaces de eventos en un lugar y llámelos // en sus propios métodos según sea necesario. $ ('ul.menu'). en ('clic', 'li.search', $ .proxy (this.toggleSearch, this)); ; var About.prototype.toggleSearch = function (e) // Alternar la función de búsqueda en la página;

Como puede ver arriba, hemos contenido las propiedades del objeto Acerca de dentro del constructor, hemos creado un único punto de referencia para eventos de enlace (en este caso estamos usando jQuery para crear los enlaces de eventos, pero puede usar cualquier marco o JavaScript en sí), y han colocado el método toggleSearch en el prototipo del objeto Acerca de para contener ese método a ese objeto. También hemos llamado al bindEvents () Método en el objeto para que se llame en instanciación..

Ahora, considere el siguiente código para la vista parcial de la barra lateral:

 var pSidebar = function (pageTitle) this.pageTitle = pageTitle; // llamar al método bindEvents en la instanciación del objeto pSidebar. // esto unirá los eventos al objeto this.bindEvents (); ; var pSidebar.prototype.bindEvents = function () // contexto actual: 'this' es el objeto Sidebar $ ('ul.menu'). en ('click', 'li.has-submenu', $ .proxy ( this.toggleSubMenu, this)); $ ('input # search'). on ('click', $ .proxy (this.openSearch, this)); ; var pSidebar.prototype.toggleSubMenu = function (e) // alternar los submenús // contexto actual: 'este' es el pSidebar obj;

NOTA: Llamé al objeto pSidebar porque esto es un vista parcial, No es una vista completa. Esta es mi preferencia para distinguir entre los dos, pero aclara las cosas..

La belleza de usar este enfoque es que podemos usar los mismos nombres de métodos que usamos en el objeto Acerca de y no tendremos conflictos. Esto se debe a que estos métodos están vinculados al objeto prototipo en sí, no el espacio de nombres global. Esto simplifica nuestro código y permite una especie de "plantillas" para futuras secuencias de comandos.


Instancia solo según sea necesario

Una vez que haya creado sus objetos, llamarlos es simple. Ya no necesita depender de su marco para desencadenar eventos cuando su documento está cargado o listo. Ahora, simplemente puede crear una instancia de su objeto y sus eventos serán vinculados y ejecutados según sea necesario. Por lo tanto, vamos a instanciar nuestra Acerca de objeto:

Dentro de la vista en la que llamaría scripts específicos para su vista (dependiendo de su lenguaje de plantillas), simplemente llame a una nueva instancia de su objeto e incluya el archivo de la siguiente manera:

  

Como puede ver, pasé el título de la página para la vista (lo que puede ser cualquier argumento para cualquier necesidad, incluso Datos del modelo. Esto le brinda un excelente contexto sobre los datos de su modelo y le permite manipular esos datos en JavaScript muy fácilmente.

Como tu Acerca de Objeto, llamar a tus vistas parciales es igual de fácil. Recomendaría encarecidamente llamar a nuevas instancias de los objetos de JavaScript de vista parcial dentro del constructor del objeto, esto garantiza que solo los esté llamando según sea necesario y que estén colectivamente en un solo lugar..

 var Acerca de = function (pageTitle) this.pageTitle = pageTitle; // asignando una nueva instancia de la vista parcial de la barra lateral para consultarla más adelante this.sidebar = new pSidebar (pageTitle); // NOTA: Si no necesita hacer referencia a una vista parcial después del hecho, // simplemente puede crear una instancia de ella sin asignarla dentro del constructor del objeto, así: new pSidebar (pageTitle); // haciendo lo mismo para la vista de pie de página parcial this.footer = new pFooter (); // eventos vinculantes tan pronto como el objeto es instanciado this.bindEvents (); ;

Como puede ver, al hacer referencia al objeto de la barra lateral como una propiedad local del objeto Acerca de, ahora vinculamos esa instancia, que es un comportamiento muy natural, esta instancia ahora es la barra lateral de la página..

Si no necesita hacer referencia a una vista parcial después del hecho, puede simplemente crear una instancia de ella sin asignarla dentro del constructor del objeto, de esta forma:

 var Acerca de = function (pageTitle) this.pageTitle = pageTitle; nueva pSidebar (pageTitle); // eventos vinculantes tan pronto como el objeto es instanciado this.bindEvents (); ;

Desde aquí, todo lo que tenemos que hacer es agregar otro script a nuestros scripts llamados en nuestra vista:

   

Por qué esta técnica es beneficiosa

Una vez que esta estructura está en su lugar, podemos adaptar nuestro objeto JavaScript para que coincida con nuestra vista y aplicar los métodos necesarios a ese objeto para mantener el alcance. Al crear un objeto de vista paralela y trabajar con el prototipo de ese objeto, vemos los siguientes beneficios:

  1. La nomenclatura facilita la navegación por el código.
  2. Naturalmente, asignamos espacios de nombres a nuestros objetos, lo que reduce la necesidad de nombres de métodos largos y un uso excesivo del cierre anónimo.
  3. Poco o ningún conflicto en otro código porque nuestros métodos están en el prototipo del objeto, no en el nivel global
  4. Cuando creamos una instancia de nuestras vistas parciales dentro del constructor de objetos de nuestra Vista y las asignamos a una referencia de variable local, creamos efectivamente una copia localmente enlazada del objeto de esa Vista Parcial.
  5. Tenemos una definición firme de contexto y podemos usar la palabra clave 'esto' sin preocuparse.
  6. La depuración se vuelve clara porque todos los métodos que se muestran en la pila están enlazados en un solo lugar.

Conclusión

A medida que el patrón de diseño de MVC continúa siendo más popular en el mundo del diseño, el desarrollo de objetos de JavaScript para acompañar la manipulación de elementos DOM cambiará para adaptarse más a la manipulación específica de la vista y del evento. Al adaptar nuestros objetos de JavaScript para crear una instancia en paralelo con nuestras Vistas, podemos tener una relación de estado a mano entre los dos, una que es simétricamente de buen gusto, fácil de seguir, fácil de mantener y perfecta para la expansión como la vista crece o cambia, creando una relación permeable y expandible entre el marcado y las secuencias de comandos.

Al utilizar un Prototipo de Objeto, podemos mantener un contexto preciso en el objeto de script de nuestra Vista y expandir ese objeto con un marco de mente de desarrollo repetitivo. Luego podemos replicar este formato a través de nuestras vistas parciales, lo que nos ahorra tiempo, capacidad mental y riesgo de errores y comportamiento inesperado.