ClojureScript, Om y Core.async: cómo manejar eventos correctamente
(1)
He echado un vistazo al uso de Om para el diseño de sitios web de clientes enriquecidos. Esta también es mi primera vez usando core.async. Leyendo el tutorial https://github.com/swannodette/om/wiki/Basic-Tutorial He visto el uso de un canal core.async para manejar la operación de eliminación (en lugar de hacer todo el trabajo en el controlador). Tenía la impresión de que el uso de ese canal para la eliminación se realizó simplemente porque la devolución de llamada se declaró en un ámbito en el que tiene un cursor en un nivel de elemento en el que realmente desea manipular la lista que contiene ese elemento.
Para obtener más información sobre los canales, he visto la charla de Rich Hickey http://www.infoq.com/presentations/clojure-core-async donde explica cómo es una buena idea usar canales para obtener la lógica de la aplicación a partir de devoluciones de llamadas de eventos. Esto me hizo preguntarme si el propósito real del canal de eliminación en el tutorial era mostrar esa forma de estructurar una aplicación. Si es así,
¿Cuáles son las mejores prácticas asociadas con ese patrón?
¿Se deben crear canales individuales para todo tipo de eventos? Es decir, si agrego un controlador para crear un nuevo evento, ¿también crearía un nuevo canal para la creación de objetos que luego se usa para que los objetos se agreguen al estado global en otro lugar de la aplicación?
Digamos que tengo una lista de elementos, y uno de ellos tiene un indicador de estado detallado / conciso. Si se
detailed?
¿Estrue
que se mostrará más información, si sedetailed?
esfalse
mostrará menos información. ¡He asociado un evento de clic que utilizaom/transact!
en el cursor (es una vista del elemento de lista dentro del objeto de estado global).
(let [toggle-detail-handler
(fn [e]
(om/transact! (get-in myitem [:state])
#(conj % {:detailed? (not (:detailed? %))})))]
(html [:li {:on-click toggle-detail-handler}
"..." ]))
Me doy cuenta de que este podría ser un fragmento muy breve en el que el beneficio general de usar los canales como un medio para desvincular el evento de devolución de llamada de los cambios de la lógica real al principio no parece que valga la pena el esfuerzo, pero los beneficios generales con ejemplos más complejos lo compensan. Pero, por otro lado, la introducción de un canal adicional para un cambio tan detallado no detallado parece agregar también una buena cantidad de carga al código fuente.
Sería genial si pudiera dar algunos consejos o sugerencias u otros pensamientos sobre el tema del diseño y ponerlos en perspectiva . Me siento un poco perdido allí.
Utilizo canales para comunicarme entre componentes que no pueden comunicarse a través de cursores.
Por ejemplo, uso canales cuando:
- los componentes en comunicación no comparten el estado de la aplicación (por ejemplo, sus cursores están apuntando hacia abajo a diferentes ramas de una estructura de datos jerárquica)
- los cambios que se comunican en vivo fuera del estado de la aplicación (por ejemplo, el componente A quiere cambiar el estado local del componente B y el componente B no es un hijo de A (de lo contrario, esto se puede hacer pasando el
:state
aom/build
) - Quiero comunicarme con algo fuera del árbol de componentes Om
Tenga en cuenta que me gusta mantener el "estado del dominio" en el átomo del estado de la aplicación y el estado de la GUI en el estado local del componente. Es decir, el estado de la aplicación es lo que se procesa y el estado local es cómo . (donde "cómo" también se refiere a qué parte) Por ejemplo, si está escribiendo un editor de texto, el estado de la aplicación es el documento que se está editando y el estado local es qué página se está editando, si se selecciona negrita, etc.
En general, utilizo un solo canal de comunicación en el que [topic value]
pares de [topic value]
. Luego uso pub y sub para enrutar los mensajes. Por ejemplo, (def p (async/pub ch first))
para usar el tema para enviar eventos y (om/sub p my-ch :foo)
para recibir mensajes con el tema :foo
to my-ch
. Generalmente almaceno este canal de comunicación único en el estado compartido de Om.
Algunas veces usaré múltiples canales, pero haría esto para configurar tuberías o flujos de trabajo específicos, en lugar de mensajes de propósito general. Por ejemplo, si tengo una tubería de componentes de procesamiento que hacen cosas a un flujo de datos, entonces podría configurar esto como una cadena de canales con los puntos finales conectados a mi aplicación Om. Para el desarrollo general de la interfaz de usuario, esto es raro. También estoy jugando con un sistema de señales / ranuras Qt-esque para mis componentes de Om y todavía estoy experimentando con el uso de canales de señales compartidas, y cada señal es su propio canal. Todavía no estoy decidido cuál es el mejor enfoque.