Knockout.js é um framework MVVM muito legal, mas é claro que está faltando algumas partes ou uma boa orientação para fazer algumas partes cruciais – como meu problema usual: vincular diferentes modelos de visualização.
Espero não ter que explicar por que alguém pode querer ter muitos modelos de visão diferentes ( tosse separação de preocupações tosse ). A questão é como ligá-los de maneira adequada.
Minha “solução” inicial (hack, quickfix) era passar no View Model do qual dependia (ou seja, View Model 2 queria saber sobre uma mudança no View Model 1) e então o View Model 2 dependente assinaria um propriedade particular (ou propriedades). Aqui, eu estava pelo menos seguindo o modelo de editor / assinante, portanto, há menos acoplamento; no entanto, o View Model 2 ainda depende diretamente do View Model 1.
As questões usuais de acoplamento surgem (eu quebro tudo se mudar muito o View Model 1, e se eu quiser maneiras diferentes de alterar a mesma propriedade – o View Model 2 precisa ter todas as referências?).
Como eu disse, o hack original era apenas isso – um hack. Assim que cheguei ao segundo caso de dependências, segui minha regra de “assim que você fizer algo mais de uma vez, encontre uma maneira melhor de fazer” (o truque é sempre estar ciente do que você está fazendo mais do que uma vez) – então eu procurei e encontrei este (até agora) adorável plugin Knockout: knockout-postbox
Funciona mais ou menos no mesmo princípio de editor / assinante que eu estava usando, mas de uma forma muito mais dissociada e limpa.
Ele usa o conceito de ‘tópicos’, em que certas propriedades publicarão para () um tópico sempre que forem alteradas. Em modelos de visualização que precisam saber sobre essas mudanças, as propriedades devem subscrever a () esse tópico para receber atualizações.
Exemplo:
function PublisherViewModel() {
this.mode = ko.observable('something').publishOn('viewmode');
this.viewModeSelection = function() { this.mode('newmode'); }
}
function SubscribeViewModel() {
this.viewMode = ko.observable('something').subscribeTo('viewmode');
}
Portanto, sempre que o modo muda em PublisherViewModel, o SubscribeViewModel () receberá mudanças em sua propriedade viewMode.
Se você tiver um código que não seja Knockout, poderá usar a API da caixa de correio para se inscrever em atualizações de tópicos (verifique o código em https://github.com/rniemeyer/knockout-postbox para ver um exemplo).
Claro, com o modelo acima você terá a duplicação da mesma propriedade em muitos modelos de visualização. Acho que deve haver uma maneira melhor de lidar com isso, mas não tive de fazer isso vezes (ainda) o suficiente para garantir encontrar algo melhor.