2012-06-28 9 views
5

Estoy tratando de implementar una aplicación de página única basada en MVVM y actualmente estoy usando el marco Knockout.js para manejar la porción viewmodel/view de MVVM. Sin embargo, estoy confundido, ya que cada ejemplo que he analizado para implementar Knockout implica guardar un modelo de vista completo en la base de datos. ¿No faltan estos ejemplos en un paso de "modelo", donde el modelo de vista se sincroniza con el modelo de capa de datos y el modelo realiza la sincronización de validación/servidor.MVVM con Knockout.js

Me gustaría tener múltiples plantillas/vistas diferentes en una sola página, cada una con un modelo de vista diferente. Otra cosa que encuentro que falta con knockout.js es sincronizar un solo modelo (no un modelo de vista) a través de diferentes vistas. No creo que tenga sentido tener un modelo de vista gigante que cada vista comparta, así que pensé que cada vista tendría su propio modelo de vista, pero cada modelo de vista se sincronizaría con los campos de solo algunos modelos de toda la aplicación necesarios para cada vista.

La página en la que estoy trabajando recupera un modelo gigante (más de 30 campos, varias capas de relaciones padre/hijo) y creo que tiene sentido que todos mis modos de vista se sincronicen con este modelo. Investigué Knockback.js (que combina knockout.js y backbone.js) sin embargo terminé reescribiendo la mayoría de las funciones como fetch, set, save, porque la página está obteniendo datos de una API (y puedo simplemente sincronizamos un modelo completo de ida y vuelta con el servidor), así que decidí no hacerlo.

ejemplo visual de mi solicitud:

(capa del modelo) M | M

(viewmodel/view layer) VM-V | VM-V | VM-V | VM-V


otro ejemplo

Un ejemplo sería el modelo de usuario = {nombre: "primero", lastName: "pasado", ...}

un modelo de vista sólo tiene nombre de pila, otro modelo de vista sólo necesita apellido
ViewModelA = {nOMBRE: app.User.firstName()} = {
ViewModelB nombre: app.User.lastName()}

¿Es la única manera de hacer esto para definir un sistema de publicación/publicación para los cambios de modelo y modelo de vista? ¿Es esta una arquitectura buena/mantenible? ¿Me estoy perdiendo un concepto básico aquí? Todos los consejos son bienvenidos.

Respuesta

5

Si leo esto correctamente, hay un montón de preguntas aquí todas enfocadas en cómo construir un MVVM/SPA con Knockout. Hay algunas cosas que hacer, como usted señaló. Una es cómo comunicarse entre los pares de viewmodel/view.

Maestro ViewModel Una manera de hacerlo es tener un modelo de vista maestra como la respuesta de @Tyrsius. Su caparazón podría tener un modelo de vista que vincula más datos disponibles. El modelo de vista maestro también podría orquestar los modelos de vista infantil. Si sigue esta ruta, debe tener cuidado de unir el caparazón externo al modelo de vista maestro y los internos a elementos HTML específicos en el DOM. El modelo de vista maestro podría facilitar la comunicación entre ellos si fuera necesario.

pares Decoupled Ver/ViewModel Otra opción es utilizar ViewModel/view pares y sin viewmodel maestro. Cada vista se carga en una región del DOM y se vincula por sí misma. Actúan como unidades separadas y están desacopladas entre sí. Puede usar pub/sub para hablar entre ellos, pero si todo lo que necesita es una manera de sincronizar los datos mediante observables, Knockout ofrece muchas opciones. El que me gusta es tener cada modelo de superficie de modelo objetos. Por lo tanto, una vista tiene un modelo de vista que muestra los datos (de un modelo) que son específicos para la vista. Tantos modelos de vista pueden aparecer en el mismo modelo de diferentes maneras. Por lo tanto, cuando una vista actualiza una propiedad de modelo de vista (que está en un modelo), se ondula a cualquier otro modelo de vista cargado que también use el mismo modelo.

DataContext Yendo un poco más allá, puede crear un módulo de contexto de datos que administre los datos en los modelos. Solicitas el contexto de datos para un modelo (por ejemplo, una lista de clientes) y el control de datos comprueba si ya los ha modificado y si no, los obtiene de una llamada ajax. De cualquier forma que se abstraiga del modelo de vista y los modelos. El contexto de datos obtiene los datos y devuelve un modelo (s) al modelo de vista. De esta manera está muy desacoplado, pero puede compartir los datos (sus modelos) a través del contexto de datos.

Podría seguir y seguir ... pero por favor dígame si esto está respondiendo su pregunta. Si no, feliz de responder cualquier otro detalle.

** Exención de responsabilidad: Estoy construyendo un curso en Pluralsight de SPA (usando Knockout y esta estrategia) :-)

+0

+1 por mencionar pub/sub, olvidé mencionar eso. – Tyrsius

+0

En primer lugar, perdón por la respuesta tardía John y @Tysirius, me pusieron en otro proyecto durante la semana pasada. Me gusta mucho la estructura desacoplada V/VM que estás sugiriendo. Me gusta la idea de que persista un modelo general independientemente de la "página" en la que esté en el SPA. Esencialmente, cómo lo interpreté fue que tengo un modelo que tiene, por ejemplo, 10 campos (ahora todos ko.observable()), luego múltiples modelos de visualización que se sincronizan con una representación parcial de ese modelo (solo algunos de los campos)), y la "ondulación" está funcionando brillantemente. –

+0

Me alegra saber que funciona para usted. Es un patrón sólido IMO. –

2

Este es un popular campo de interés en este momento, por lo que espero que obtenga algunas mejores respuestas, pero aquí va.

El Modelo

Sí, usted debe tener absolutamente una representación del lado del servidor de los datos, que es su modelo. Lo que esto depende depende de su servidor y su base de datos. Para MVC3, este es su modelo de entidad. Para Django o Ruby, habrá definido modelos de db como parte de su configuración de db. Esta parte depende de tu tecnología específica. Pero agian, debe tener un modelo, y el servidor debe absolutamente realizar la validación de datos.

la solicitud (modelo de vista)

Se recomienda que sus puntos de vista cada uno tiene su propio modelo de vista.Su página también podría tener un modelo de vista, un modelo de vista de aplicación si lo desea, que realiza un seguimiento de todos ellos. Si realiza esta ruta, el modelo de vista de la aplicación debe ser responsable de cambiar entre las vistas e implementar cualquier otra lógica de nivel de aplicación (como la navegación con hash bashed, otra herramienta popular de una sola página). Esta jerarquía es muy importante, pero no siempre es simple. Se reducirá a los requisitos específicos de su aplicación. No estás limitado a un modelo de vista plano. Este no es el único método posible.

Ad Hoc Ejemplo:

​var ThingViewModel = function(name, data){ 
    this.name = ko.observable(name); 
    //Additional viewmodel stuffs 
}; 

var AppViewModel = function(initialData){ 
    //Process initial data  
    this.thing = new ThingViewModel(someName, someData); 

}; 

estoy trabajando en un proyecto similar en este momento, únicamente para el estudio (no una verdadera aplicación mundial), que está alojada here on GitHub, si desea echar un vistazo a las algunos ejemplos reales. Tenga en cuenta que la rama dev está bastante adelantada a la rama master en este momento. Estoy seguro de que contiene algunos malos patrones (no dudes en señalarlos, estoy aprendiendo también), pero de todos modos podrías aprender algunas cosas.

+0

¡Hola! - re: su punto sobre "debería tener absolutamente una representación de los datos en el servidor", ¿significa esto que cada cambio en su modelo de vista debería pasar primero por el servidor? – MikeW

+0

¡Absolutamente no! Lo que quería decir es que debería existir una clase de modelo en el servidor, porque el servidor está conservando estos datos (generalmente en una base de datos) y el servidor tiene que trabajar con ellos. Las operaciones del modelo de vista eliminada deberían permanecer en el cliente * tanto como sea posible *. – Tyrsius

1

tengo una solución igualmente compleja en la que estoy reelaboración una aplicación de WPF en una versión web. La versión de WPF se ocupó de objetos de dominio complejos que vinculó a vistas mediante modelos de presentador.

En la versión web, he implementado modelos de vista del servidor simplificados y algo aplanados que se traducen hacia y desde objetos de dominio utilizando Automapper. A continuación, los modelos de vista del lado del servidor se envían al cliente como JSON y se mapean en/en los modelos de vista Knockout correspondientes (funciones instanciables que cada uno asume la responsabilidad de crear sus hijos con opciones de submapeo) usando el plugin de mapeo.

Cuando necesito guardar/validar mi UI, vuelvo a mapear todo o parte de mi modelo de vista eliminatoria a un objeto Javascript plano, lo publico como JSON, el marco MVC lo vincula a modelos de vista del servidor, estos vuelva a automatizarse en objetos de dominio, validados y posiblemente actualizados por nuestra capa de dominio, y luego se devuelva y vuelva a correlacionar un gráfico completo o parcial revisado.

Actualmente tengo solo una página principal donde se lleva a cabo la acción Knockout, pero anticipo que, como usted, terminaré con varios contextos que necesitan tratar con el mismo modelo (mis objetos de dominio) extraídos como diferentes modelos de visualización dependiendo de lo que estoy haciendo con ellos.

He estructurado los directorios del modelo de vista lateral del servidor, etc., anticipándome a esto, así como a la estructura de mis modelos de vista Knockout. Hasta ahora, este enfoque funciona bien. Espero que esto ayude.

+0

gracias por esta respuesta, todavía no comencé el mapeo JSON, ¡pero estoy seguro de que será útil! –

0

Durante un proyecto, desarrollé un marco (que utiliza KnockoutJS) que proporciona pares desacoplados View/ViewModel y permite instanciar subvistas en una vista. El marco de trabajo proporciona todo el manejo de la vista y la creación de instancias de la subvista. Funciona como MVVM con XAML en WPF.

Echa un vistazo a http://visto.codeplex.com