Não foi possível carregar o Diqus. Se você é o moderador, por favor veja o nosso guia de problemas.
Eu provavelmente vou fazer algum adapter para o Module. Esse dispatcher existe bem antes do Module.js. :)
Uso o Dispatcher há um bom tempo, e quando comecei a usar o Turbolinks nas minhas aplicações, tive que fazer algumas adaptações.
Acabei de atualizar um dos meus projetos com essa nova versão e ficou perfeito!
O helper acho que dá pra simplificar: https://gist.github.com/Fab.... O que acha?
Acho ótimo! Já atualizei o artigo e o README. ;)
A despeito do Dispatcher ser escrito com comma first, preciso deixar um ponto contra. Este tipo de abordagem é interessante quando a intenção é espelhar o back-end diretamente no front-end. Código baseado em rotas engessa a aplicação, os motivos estão por aqui http://jcemer.com/atribuind....
Mas não digo que seja uma solução ruim, muitas tecnologias são baseadas em rotas. O bom é considerar bem o seu problema antes de adotar uma solução, ainda mais se a intenção for modularizar. :)
A despeito do Dispatcher ser escrito com comma first, preciso deixar um ponto contra
Meh. No fim, vou usar o minificado.
Código baseado em rotas engessa a aplicação
Não é verdade. Faço isso há pelo menos 7 anos e nunca ficou engessado. O que engessa é colocar toda a lógica dos componentes na função da rota, que é exatamente o que aviso no último parágrafo, sobre inicializar os objetos necessários.
O bom é considerar bem o seu problema antes de adotar uma solução, ainda mais se a intenção for modularizar. :)
Código modular nada tem a ver com código reutilizável. Código modular tem a ver com responsabilidades bem definidas, e não vejo como o uso de rotas pode impedir que isso aconteça. ;)
Não digo que o ponto seja reuso. Apenas penso que, para algumas muitas aplicações, não é responsabilidade da página (leia, rota) disparar os comportamentos. Para os casos em que componentes migram de página em página, faz mais sentido que eles próprios cuidem do seu nariz.
Só elaborando um pouco mais sobre a parte de modularidade. Eu normalmente uso esta solução baseada em rotas para inicializar outros componentes.
Imagine que em uma lista existe a possibilidade de marcar/desmarcar os ítens como "liked". Nos meus projetos, uso minha biblioteca Module. A rota faria apenas isso:
// app/assets/javascripts/myapp/routes/things.js
Module("MyApp.routes.things", function(things){
things.index = function() {
MyApp.List($(".list")).init();
};
}, {});
Note que o componente MyApp.List não usa referências globais do DOM e sempre irá receber os objetos à partir da rota. Tudo o que faço recebe argumentos; além de tornar o código reutilizável quando fizer sentido, posso escrever testes facilmente, já que quase sempre os testes nem precisam que o elemento exista no DOM. De novo, a ideia de rotas apenas facilita essa inicialização.
Uma curiosidade: nesse mesmo exemplo que dei, como seria a sua abordagem? Como você executa JavaScript no contexto de uma página? Usa content_for para inicializar o JS ou algo do tipo?
O DOM é quem indica o comportamento. Quando entendo que se trata de um componente, que é caso da lista que você ilustrou, ela terá um atributo `data-components` com o valor list. Um dispatcher varre o DOM a procura de todos os elementos com este atributo e inicia o componente.
Outro caso é quando não atende a esta regra de componentes. Um botão que dispara uma modal, por exemplo. Para estes, utilizo atributos prefixados com `data-` específicos e sempre tenho listeners (no document) ou procuro por estes elementos na página.
Desta maneira, não penso mais a aplicação como por páginas e os comportamentos sempre serão iniciados. Tem funcionado bem. xD
Então, é o componente é que se auto-registra? Parece estranho. Isso significa que seu tiver 10 componentes, você deixa tudo sendo inicializado, mesmo quando ele não vai ser utilizado em uma determinada página, já que você não trabalha com o conceito de JavaScript por página.
E seguindo sua abordagem, significa também que o elemento precisa existir no DOM para que um teste seja escrito.
Eu ainda prefiro uma abordagem mais explícita de inicialização de componentes, que recebe seu contexto de DOM onde pode atuar. Mas pode ser uma abordagem a testar no futuro.
Não, o HTML terá a informação de qual componente deve ser instanciado e com qual elemento. No fim vou ter um simples `new List(element)`.
O dispatcher sim depende do DOM, ele é quem busca os elementos. Os componentes só recebem um elemento e posso continuar testando sem nenhum problema.
Tem exemplos aqui http://jcemer.com/piecemake...
Ah, estão existe um dispatcher. O que significa que você faz mesma coisa que eu, só que de uma maneira diferente. A sua rota é o atributo data que seu dispatcher espera.
Como você insere esses atributos data em um app Rails?
Hehe, em cada elemento. Veja, existe alguém que gerencia, mas ele é a nível de elemento e não de página. Não digo que seja melhor ou pior, mas é bem diferente.
Os atributos vão no elemento mesmo `<ul data-components="list">`.
Entendi claramente, agora. Acho uma boa abordagem. Pode ser que eu teste fazer isso no futuro. ;)
Muito boa esta abordagem. Com certeza pensarei em implementá-la nos próximos projetos.
Fui traído pela reescrita. Deixando mais claro: o comma first é ponto a favor a meu ver. :)
Só pra não trair meus princípios e parecer incoerente.
Oi Nando! Excelente artigo! Você sabe como eu poderia organizar cada action em um arquivo separado, assim como nas views?
Interessante a técnica, Nando. Gostei do teu approach principalmente por ser baseado no conceito de rotas (e por estar disponibilizado pelo Bower ❤).
No Magnetis temos um cara chamado `ModuleLoader` que sabe que controller tem que inicializar através da classe que adicionamos no body pelo Rails (controller + action).
Nisso ele dá um `fetch()` na classe que precisa ser inicializada e boa.