Vue: vuejs2.0 deve manter a API de evento $ broadcast, $ dispatch? Nenhuma boa solução para abordar a comunicação ponto a ponto entre pais e filhos em 2.0

Criado em 1 set. 2016  ·  41Comentários  ·  Fonte: vuejs/vue

@ yyx990803 ,
Olá, equipe principal do Vuejs,
Estou lutando para encontrar uma boa solução para a comunicação ponto a ponto entre os componentes pai e filho com o vuejs2.0.
Como vuejs2.0 tornou-se obsoleto o $ broadcast, $ dispatch api, é muito difícil para mim encontrar uma solução alternativa $ broadcast, $ dispatch fornece o recurso de barramento de evento vuejs2.0.
Eu escrevi um tópico no fórum sobre este tópico aqui e gostaria de colá-lo aqui para mais discussão.

POR FAVOR, NÃO FECHE A MENOS QUE tenha uma boa ideia ou solução no vuejs2.0.

<pcom id=1>
    <soncoma></soncoma>
    <soncomb></soncomb>
</pcom>
<pcom id=2>
    <soncoma></soncoma>
    <soncomb></soncomb>
</pcom>

No código acima, quando filho de pcom1, por exemplo, soncoma $ emite um evento, digamos,

bus.$emit('son-coma-event',somedata)

no pcom, ouvimos esse evento com

bus.$on('son-coma-event',function(){})

Eu só quero que o pcom1 trate desse evento, mas infelizmente o pcom2 também fará isso.
Como lidar com essa condição?

Uma das soluções alternativas em meu aplicativo é usar this. $ Parent como barramento de eventos
Em criança:

this.$parent.$emit('some-event',someData)

No pai:

{
   created(){
       this.$on('some-event',function(){})
}

O ponto negativo para a solução alternativa acima é:

  1. acoplamos muito na relação pai-filho;
  2. não funciona se houver um nível mais aprofundado dos níveis pai-filho;

Em algumas condições mais complexas, será mais difícil encontrar uma boa solução para o sistema de eventos personalizados, por exemplo, um componente recursivo

 <pcom>
    <recursivechild>
             <recursivechild>
                          <recursivechild>
                          </recursivechild>
             </recursivechild>
    <recursivechild>
</pcom>

 <pcom>
    <recursivechild>
             <recursivechild>
                          <recursivechild>
                          </recursivechild>
             </recursivechild>
    <recursivechild>
</pcom>

como a criança recursiva se comunica com seu componente pcom direto?
Por favor, dê sua ideia ou sugestão sobre esses tópicos.
Obrigado ~!

discussion

Comentários muito úteis

@rhyek , gostaria de falar sobre alguns pontos que você levantou. Como a discussão já abordou vários tópicos, gostaria de voltar ao básico sobre por que descontinuamos $ diospatch e $ broacast:

1. acoplamento implícito.

Se você tem um pai e um filho profundamente aninhado que despacha um evento, não há como inferir essa relação a partir do código (e o mesmo é verdadeiro para $broadcast , oviously.)

Se você olhar para as outras mudanças e depreciações que introduzimos com o Vue 2.0, você pode perceber que remover o comportamento implícito em favor de alternativas explícitas é um tema comum, e descontinuar $dispatch se encaixa bem aí.

Exemplo:

// parent
events: {
  'some-event': function () { ... }
}

// deeply nested child:
$dispatch('some-event')

Isso é bom quando o pai tem apenas um filho direto - mas, nesse caso, $emit() com um ouvinte no modelo também não é um trabalho extra real.

Torna-se difícil acompanhar (especialmente em equipes) assim que você tem filhos aninhados (especialmente profundamente aninhados), ou mesmo mais de um filho direto - você tem que examinar todos os filhos ou confiar em comentários de código para documentar qual evento é determinado a partir de qual componente filho - que também é um clichê adicional.

Você diz que gosta de $ dispatch e $ broadcast porque não precisa passá-los por outros componentes. E posso concordar que é mais fácil - mas não nos deparamos com muitas situações em que isso fosse realmente necessário, ou melhor: se houvesse tal cadeia de omissão de um evento, seria preferível que os dados fossem alterados / anexado / durante esta viagem por componente intermediário.

2. Nomes de eventos

quando você usa $dispatch com componentes profundamente aninhados, você teria que ser muito explícito no namespace de seus eventos, porque do contrário, eles poderiam ser conflitantes:

// parent
events: {
  'close': function () { ... }
}

// deeply nested child 1:
$dispatch('close')
// deeply nested child 2:
$dispatch('close')

..e se essas crianças são libs de terceiros, você está ferrado agora. ou tem que capturar o evento em algum componente no meio apenas para renomeá-lo antes de $dispatch() mais para o pai. E não se esqueça de comentar isso, porque alguém olhando para este código pode pensar por que você não faz outra coisa com um evento além de renomeá-lo.

Usar $ emit e ouvintes de modelo não tem esse problema. você pode usar nomes de eventos curtos e simples em qualquer lugar, eles não entrarão em conflito, pois cada evento tem seu próprio retorno de chamada anexado ao modelo @close="callback ".

Eu realmente só queria que você não retirasse a * escolha * de usar qualquer um dos paradigmas,

Se pensássemos que os dois paradigmas podem funcionar igualmente bem, nós os trataríamos igualmente. Mas não pensamos assim, pelas razões acima e muito mais.

Portanto, tentamos direcionar os usuários para os pactos que achamos que funcionam melhor, enquanto deixamos uma maneira de contorná-los com o método "barramento global".

Também gostaria de falar sobre suas preocupações com o estado global, mas não tenho certeza se entendi totalmente sua posição ainda.

Talvez você possa fornecer um exemplo em que você acha que $ dispatch e $ broadcast funcionam melhor para você, e eu tento mostrar como "nossa" abordagem poderia melhorar a situação.

Todos 41 comentários

Por se tratar de uma discussão de proposta geral, ainda não criei violino. Se for necessário, gostaria de criar para demonstrar.
obrigado ~!

Isso já foi justificado nas Mudanças 2.0

Aqui está uma cópia:

Como lidar com a suspensão de uso de $dispatch e $broadcast ?

O motivo de estarmos descontinuando $dispatch e $broadcast é que os fluxos de eventos que dependem da estrutura da árvore de componentes podem ser difíceis de raciocinar sobre quando a árvore de componentes se torna grande (basta colocar: não escalar bem em aplicativos grandes e não queremos configurá-lo para dor mais tarde). $dispatch e $broadcast também não resolvem a comunicação entre componentes irmãos. Em vez disso, você pode usar um padrão semelhante ao EventEmitter no Node.js : um hub de eventos centralizado que permite que os componentes se comuniquem, não importa onde estejam na árvore de componentes. Como as instâncias do Vue implementam a interface do emissor de evento, você pode usar uma instância vazia do Vue para essa finalidade:

var bus = new Vue()
// in component A's method
bus.$emit('id-selected', 1)
// in component B's created hook
bus.$on('id-selected', function (id) {
 // ...
})

Este padrão pode servir como um substituto para $dispatch e $broadcast em cenários simples. Porém, para casos mais complexos, é recomendável introduzir uma camada de gerenciamento de estado dedicada usando o Vuex .

O exemplo mostrado no guia de atualização é o mesmo que você está falando

Sobre a comunicação recursiva: vários componentes podem ouvir o mesmo evento. Este evento é reconhecido pelo pai comum para que todas as crianças possam estar cientes dele

@posva , obrigado pela sua informação. o hub de barramento realmente funciona bem em uma comunicação simples de um único ponto de componente para um único ponto de componente. Se houver vários componentes com o mesmo tipo de componente, haverá problema, infelizmente, este é um caso normal. Muitos casos, o que eu quero usar o evento é atualizar um pequeno dado pertencente a algum componente específico. A implementação do barramento de evento atual não fornece informações sobre o destino ou nó de origem (eu vi _uid de todos os componentes, talvez possamos usar este _uid exclusivo para a conexão do evento?), Então vuejs2.0 não pode suportar comunicação de evento ponto a ponto de fato . Para ser exato, o barramento de eventos vuejs2.0 suporta apenas comunicação de tipo de componente para tipo de componente? Existe uma solução simples para atender a esse requisito: acionado por um evento na árvore e atualizar seus próprios dados
O vuex é ótimo para gerenciamento de dados de estado estático global em nível de aplicativo, mas, pelo que entendi, talvez não seja bom para gerenciamento de dados de componentes locais específicos.
Mais pensamento é bem-vindo sobre este assunto.

@cnweibo Respondi sua pergunta com um exemplo no fórum. Acho que este exemplo irá atender às suas necessidades.
http://forum.vuejs.org/topic/4832/vue2-0-event-bus-issue-how-to-deliver-event-to-parent-when-the-same-multiple-parent-children-in- dom / 6

Existe uma solução simples para atender a esse requisito: acionado por um
evento na árvore e atualizar SEUS PRÓPRIOS DADOS

Isso é resolvido simplesmente por vuex, sem um sistema de eventos complicado.

vuex é ótimo para gerenciamento de dados de estado estático global em nível de aplicativo,
mas, pelo que entendi, talvez não seja bom para dados de componentes locais específicos
gestão

'local' significa apenas um componente. Seu caso de uso é o gerenciamento de estado em
vários componentes, portanto, é global.
E vuex pode ter módulos (subárvores de estado), então não é uma 'variável global'
tipo de 'global'. Você pode conduzir grupos de componentes com seu próprio vuex
módulos.

Toda essa discussão de 'eventos vs. estados compartilhados' foi resolvida meses
atrás, e a conclusão é usar o barramento de evento global ou vuex. Então eu
recomendo que você leia mais sobre o vuex e como ele funciona.

Em Qui, 1º de setembro de 2016, 16:17 cnweibo [email protected] escreveu:

@posva https://github.com/posva , obrigado pela sua informação. o ônibus
hub realmente funciona bem em um simples ponto de componente único para um único componente
ponto de comunicação. Se houver vários componentes com o mesmo componente
tipo, vai haver problema, infelizmente, esse é um caso normal. Muitos
casos, o que eu quero usar é um evento para atualizar um pequeno dado pertencente a algum
componente específico. A implementação do barramento de evento atual não dá
informações sobre destino ou nó de origem (eu vi _uid de cada
componente, talvez possamos usar este _uid exclusivo para a fiação do evento? ), tão
O vuejs2.0 não pode oferecer suporte a comunicação de evento ponto a ponto, de fato. Ser estar
Exato, o barramento de evento vuejs2.0 suporta apenas tipo de componente para tipo de componente
comunicação? Existe uma solução simples para atender a esse requisito:
acionado por um evento na árvore e atualizar _ITS PRÓPRIOS DATA_
vuex é ótimo para gerenciamento de dados de estado estático global em nível de aplicativo,
mas, pelo que entendi, talvez não seja bom para dados de componentes locais específicos
gestão?

Mais pensamento é bem-vindo sobre este assunto.

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/vuejs/vue/issues/3581#issuecomment -244008699 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AFTLl1bjHqWTVDAkr8Fqbx0WiTuH16n2ks5qlooBgaJpZM4JyUfJ
.

Vou encerrar agora este problema, porque

  1. Soluções foram fornecidas e
  2. De qualquer forma, os problemas do Github não são o lugar certo para solicitar suporte (consulte as Diretrizes)

@ktsn , obrigado pelo seu violino de demonstração. É exatamente isso que quero uma solução simples!
@fnlctrl , vou dedicar mais tempo ao chamado gerenciamento modular de estado vuex

obrigado novamente ~!

Na minha opinião, $ broadcast não é necessário, apenas fluxo de dados de adereços em queda.
Qualquer $ dispatch pode ser reimplementado como v-on de nível único e $ emit assim (no Vue 1):
<child-component @select="$emit('select', $arguments[0])" /> em cada componente envolvido
Em qualquer outra situação, os ônibus de eventos personalizados devem ser usados

Na verdade, o v-on na tag do componente para evento customizado no próprio componente funciona bem com $ emit do próprio componente.

@cnweibo Para registro, os dados do evento podem ser recuperados.

{
  template: `<foo @bar="dosomething">`,
  methods: {
    dosomething(params1, params2, ... and all the event data args) {}
  }
}

Mas os dados do evento não podem ser recuperados em vuejs2.0

Claro que pode, o que o faz pensar o contrário?

@fnlctrl
@LinusBorg
Desculpe, eu tenho entendido mal e não deixo as coisas claras. no padrão @fnlctrl fornecido, realmente pode recuperar todos os dados em seu manipulador de eventos, mesmo com

 <comp @some-event-emitted-by-comp-internal-template="someFuncInParentScope"></comp>

Copie / cole meu próprio comentário de outro problema: https://github.com/vuejs/vue/issues/2760#issuecomment -250883407

Acho que remover $ dispatch foi uma ideia terrível. Este não foi o primeiro framework / biblioteca de interface do usuário a implementar a noção de ações / eventos borbulhantes em uma árvore visual. É uma ideia bem estabelecida. Por que retirar essa funcionalidade com a premissa de que "ser capaz de despachar um evento que causa efeitos colaterais em sua árvore pai desconhecida soa como uma receita para problemas para mim"? Você precisa deixar essa responsabilidade para os usuários. Tenho certeza de que a maioria tem o bom senso para usar esse recurso de maneira adequada. Não é um conceito novo!

Eu realmente não consigo ver o benefício dessa mudança quando esta biblioteca é construída sobre tecnologias / conceitos da web estabelecidos há muito tempo, como os eventos DOM e DOM que de fato borbulham na árvore visual e têm feito isso há anos sem ninguém reclamando. A ideia de componentes não é algo que foi recentemente adotado graças à proposta do W3C para componentes da web? Na minha opinião, só faz sentido que os componentes do Vue se comportem de maneira semelhante aos elementos regulares do DOM no que diz respeito a como o tratamento de eventos é feito.

A alternativa proposta para usar um ônibus global de eventos me parece ilógica quando algo mais prático, eficaz e fácil de entender (por ser um conceito bem estabelecido há anos) já existia.

Outras propostas neste tópico me lembram de como o EmberJS deseja fazer isso. Passar ações de fechamento como propriedades para os componentes em cada nível da hierarquia. Tão tedioso e desnecessário! Vuejs foi a razão pela qual escrevi https://www.npmjs.com/package/ember-component-action-bubbling!

Além disso, gosto muito da sua biblioteca. Mas, falando sério, acho que foi uma mudança terrível.

O paradigma de barramento de eventos foi proposto apenas como uma solução para fazer exatamente a mesma coisa, quando uma arquitetura baseada em eventos é muitas vezes inferior a uma arquitetura declarativa baseada em estados.

Digamos, você tem um aplicativo onde o usuário pode fazer login. Com uma solução baseada em eventos:

  1. Ouça um evento de login
  2. Dispare o evento mais tarde com o nome de usuário e senha
  3. Responda ao referido evento de acordo com quaisquer componentes que estejam ouvindo

No entanto, isso traz alguns problemas. O maior deles é que os componentes que não estão sendo renderizados no DOM quando o evento é disparado não vão receber a mudança, junto com você não saber quais partes do aplicativo irão receber o evento. Além disso, os destinatários do evento não podem saber de onde o evento está vindo sem informações adicionais fornecidas. Desculpe minha linguagem, mas isso é uma confusão enorme com que lidei e não quero usar novamente.

Então, vamos usar uma abordagem com estado:

  1. Crie uma variável de estado global que representa as informações da conta do usuário. É null quando desconectado e contém as informações de login do usuário quando conectado.
  2. Quando o usuário fizer login, defina as informações da conta.

Tudo no aplicativo que depende dessa variável de estado é atualizado de acordo. Sem eventos e não importa quando ou onde o componente é criado, porque ele sempre exibirá as informações corretas. Você poderia usar um evento para atualizar o estado global, mas por que fazer isso quando você pode apenas ... atualizá-lo?

Uma abordagem declarativa permite que você escreva seus componentes de uma maneira que sempre apareça da mesma maneira, dependendo exatamente do estado local / global, independentemente do que o usuário faz em sua aplicação, sem ter que ouvir o que acontece. Eu acredito que Vue foi feito para isso o tempo todo, mas assim como acontece com a maioria das coisas no desenvolvimento de software, demoramos um pouco para descobrir isso. Mas estou muito feliz por termos feito isso.

EDIT: Ah, e não se esqueça de que você pode observar os parâmetros e, digamos, enviar uma solicitação AJAX ou realizar alguma outra ação quando ela mudar. por exemplo, depois que um usuário loga, observe a variável 'loggingIn', quando for verdade, carregue suas imagens de perfil, ou algo parecido.

Eu entendo o que você está dizendo, mas ter algum componente aleatório modificando o estado global é, eu acho, a mesma coisa que ter aquele componente aleatório borbulhando um evento sabe Deus onde. Você ainda corre o mesmo risco de ter o fluxo de seu aplicativo "sujo" acidentalmente.

Existem maneiras de lidar com ambos os paradigmas de maneira limpa e que normalmente (e devem) acabar sendo responsabilidade do usuário do framework.

Haverá certas situações em que um mecanismo fará mais sentido do que o outro. Por exemplo, concordo que um estado conectado deve ser algo conhecido por todo o seu aplicativo: o estado global faz sentido. Mas o botão no qual o usuário do aplicativo clica geralmente não vai lidar com a lógica por trás de realmente fazer o login do usuário. Isso será algo manipulado mais acima na cadeia. Pode ser um componente, pode ser uma rota. O botão provavelmente precisará apenas notificar algo sobre a intenção de fazer login. O botão, portanto, não precisa modificar seu estado global diretamente.

Portanto, agora, com a remoção de $ dispatch, você precisa que o componente de botão saiba sobre algum objeto global que gerencia a sessão de usuário do aplicativo e o notifique diretamente sobre a intenção. Isso torna o botão fortemente acoplado a todo o seu aplicativo.

Ou você pode ter o botão aninhado em 10 níveis de profundidade e deve declarar um manipulador v-on:login em cada nível para que a intenção alcance seu destino. Totalmente desnecessário.

Na verdade, ter que fazer v-on em todos os níveis apenas torna seu código mais difícil de manter.

Bem, obviamente, apenas alterar diretamente o estado pode ser problemático, mas Vuex resolve esse problema com mutações e ações. E é verdade que algumas soluções se encaixam melhor do que outras, mas nunca encontrei uma situação em que a lógica declarativa não fosse a melhor opção.

No seu caso específico, provavelmente não faria um botão específico para fazer login, heh. Além disso, se um componente relacionado ao login estiver aninhado tão profundamente por algum motivo, basta fazer com que ele mude de estado global.

O botão de login foi apenas um exemplo. E uma loja vuex é a que me referia quando mencionei "algum objeto global". Eu teria que verificar como o vuex funciona, mas espero que você esteja acoplando fortemente algum componente aleatório ao resto do estado do seu aplicativo simplesmente tendo que gerenciar uma referência para a loja.

Isso não é desejável se, por exemplo, o botão de login fizer parte de alguma biblioteca de terceiros.

Eu realmente gostaria que você não retirasse a * _escolha * _ de usar qualquer um dos paradigmas, especialmente quando o borbulhamento de eventos é amplamente reconhecido e, portanto, fácil de compreender para novos contribuidores em um projeto.

Depende do que você entende por "algum componente aleatório", porque um componente de exibição do roteador, por exemplo, tem todos os direitos para acessar e se comprometer com a loja na minha opinião. No entanto, se for um componente menor para reutilização, como um botão, formulário ou algum outro elemento de interface do usuário, 9 em cada 10 vezes, não deve haver nenhuma razão lógica para ele acessar a loja, usando adereços e eventos.

Como os dados em um aplicativo Vue são de cima para baixo, você deseja manter o máximo possível do seu estado local. O aninhamento profundo em si é um problema a ser evitado tanto quanto possível. Não é _isso_ muito incômodo propagar eventos dois níveis abaixo, mas é provável que você precise repensar a estrutura do seu modelo se for mais profundo do que isso.

Isso é principalmente uma tangente, no entanto. Muitas vezes, os paradigmas mais fáceis de entender são aqueles que acabam sendo abusados ​​até o fim do inferno e se tornam difíceis de manejar. Uma abordagem baseada no estado é muito mais direta, conforme acordado pela maioria de nós que atualmente usa o 2.0. Você está livre para continuar usando 1.0 ou para passar para outra estrutura se esta abordagem não for sua preferência.

9 em cada 10 vezes, não deve haver nenhuma razão lógica para ele acessar a loja, usando adereços e eventos.

Exatamente meu ponto.

O aninhamento profundo em si é um problema a ser evitado tanto quanto possível

Às vezes, isso não é uma opção.

Não é muito incômodo propagar eventos dois níveis abaixo

Não é tão verdade quando esses níveis são mais profundos.

os paradigmas mais fáceis de entender são aqueles que acabam sendo abusados ​​até o fim do inferno e se tornam pesados

Isso deve depender da disciplina dos usuários.

Você está livre para continuar usando 1.0 ou para passar para outra estrutura se esta abordagem não for sua preferência.

Mmk.

Simplicidade e conveniência é o motivo pelo qual eu estava pensando em mudar de Ember para Vue. $dispatch é uma das coisas que eu gostei no Vue e removê-lo parece tão arbitrário para mim.

A equipe removeu muitos recursos para a versão 2.0. Eu honestamente concordo com todos eles. Só não este.

Obrigado por suas respostas.

@ktsn As alternativas para $ broadcast e $ dispatch são muito simples, esta remoção veio para melhorar e ficou ainda melhor.

@rhyek , gostaria de falar sobre alguns pontos que você levantou. Como a discussão já abordou vários tópicos, gostaria de voltar ao básico sobre por que descontinuamos $ diospatch e $ broacast:

1. acoplamento implícito.

Se você tem um pai e um filho profundamente aninhado que despacha um evento, não há como inferir essa relação a partir do código (e o mesmo é verdadeiro para $broadcast , oviously.)

Se você olhar para as outras mudanças e depreciações que introduzimos com o Vue 2.0, você pode perceber que remover o comportamento implícito em favor de alternativas explícitas é um tema comum, e descontinuar $dispatch se encaixa bem aí.

Exemplo:

// parent
events: {
  'some-event': function () { ... }
}

// deeply nested child:
$dispatch('some-event')

Isso é bom quando o pai tem apenas um filho direto - mas, nesse caso, $emit() com um ouvinte no modelo também não é um trabalho extra real.

Torna-se difícil acompanhar (especialmente em equipes) assim que você tem filhos aninhados (especialmente profundamente aninhados), ou mesmo mais de um filho direto - você tem que examinar todos os filhos ou confiar em comentários de código para documentar qual evento é determinado a partir de qual componente filho - que também é um clichê adicional.

Você diz que gosta de $ dispatch e $ broadcast porque não precisa passá-los por outros componentes. E posso concordar que é mais fácil - mas não nos deparamos com muitas situações em que isso fosse realmente necessário, ou melhor: se houvesse tal cadeia de omissão de um evento, seria preferível que os dados fossem alterados / anexado / durante esta viagem por componente intermediário.

2. Nomes de eventos

quando você usa $dispatch com componentes profundamente aninhados, você teria que ser muito explícito no namespace de seus eventos, porque do contrário, eles poderiam ser conflitantes:

// parent
events: {
  'close': function () { ... }
}

// deeply nested child 1:
$dispatch('close')
// deeply nested child 2:
$dispatch('close')

..e se essas crianças são libs de terceiros, você está ferrado agora. ou tem que capturar o evento em algum componente no meio apenas para renomeá-lo antes de $dispatch() mais para o pai. E não se esqueça de comentar isso, porque alguém olhando para este código pode pensar por que você não faz outra coisa com um evento além de renomeá-lo.

Usar $ emit e ouvintes de modelo não tem esse problema. você pode usar nomes de eventos curtos e simples em qualquer lugar, eles não entrarão em conflito, pois cada evento tem seu próprio retorno de chamada anexado ao modelo @close="callback ".

Eu realmente só queria que você não retirasse a * escolha * de usar qualquer um dos paradigmas,

Se pensássemos que os dois paradigmas podem funcionar igualmente bem, nós os trataríamos igualmente. Mas não pensamos assim, pelas razões acima e muito mais.

Portanto, tentamos direcionar os usuários para os pactos que achamos que funcionam melhor, enquanto deixamos uma maneira de contorná-los com o método "barramento global".

Também gostaria de falar sobre suas preocupações com o estado global, mas não tenho certeza se entendi totalmente sua posição ainda.

Talvez você possa fornecer um exemplo em que você acha que $ dispatch e $ broadcast funcionam melhor para você, e eu tento mostrar como "nossa" abordagem poderia melhorar a situação.

Acho que $ dispatch / $ broadcast e bus de eventos tratam de coisas diferentes. Eles podem tornar o código fácil de manter e desacoplado em diferentes cenários. Se conseguirmos mantê-los dentro, será ótimo.
É muito difícil dizer que um é melhor do que outro em todos os casos.

@cnweibo Acho que houve argumentos bastante exaustivos de ambos os lados e, honestamente, não vejo seu ponto de vista sobre "abordar coisas diferentes". Sinta-se à vontade para apresentar mais argumentos, mas posso afirmar com certeza que isso não acontecerá.

Se você realmente quer isso, não é tão difícil implementá-lo como um plugin.

@LinusBorg Agradeço sinceramente o tempo que você gastou para escrever sua resposta e entendo seus argumentos.

Você diz que gosta de $ dispatch e $ broadcast

Eu apenas gosto de $dispatch , honestamente. $broadcast definitivamente parecia estranho para mim. Como eu disse, $dispatch é apenas um evento borbulhante, algo onipresente entre muitas plataformas neste momento. $broadcast ... nem tanto. A única coisa semelhante que já encontrei é "visualizar" eventos no WPF que são pareados com eventos normais. Eles "canalizam" a árvore visual do elemento superior até a origem do evento original, mas são enviados diretamente para baixo na cadeia de elementos relacionados e não se espalham para tudo.

você teria que ser muito explícito no namespace de seus eventos

Eu concordo com isso e geralmente é o que eu faço, de qualquer maneira. É também o que as pessoas estão acostumadas a fazer no jQuery. Além disso, algumas plataformas apenas enviam um objeto "fonte" como um argumento para o manipulador e talvez você possa filtrar contextos com base nisso (dica: instanceof ). Os eventos DOM têm event.target disponíveis, por exemplo. Outras plataformas têm a vantagem de trabalhar com tipos estáticos, portanto, esse "conflito" é muito difícil de encontrar (um evento é uma instância de uma classe).

Em qualquer caso, eu simplesmente não entendo por que isso é uma preocupação para a equipe VueJS. Se as pessoas não podem ser cuidadosas o suficiente ao usar $dispatch , tenho certeza de que você pode encontrar muitas outras coisas que elas estão fazendo de errado usando sua biblioteca. Até onde você irá para "proteger" seus usuários de serem descuidados?

Isso é bom quando o pai tem apenas um filho direto - mas, nesse caso, $ emit () com um ouvinte no modelo também não é um trabalho extra real.

Pergunta honesta (como sou decididamente novo no Vue), além de declarar ouvintes em todos os níveis, você também não precisa $emit o evento em cada componente da cadeia? Isso parece tão irritante.

Para concluir, deixe-me citar algo que alguém disse sobre um problema no vue-cli sobre a introdução de "modelos oficiais" para novos projetos (https://github.com/vuejs/vue-cli/issues/123#issuecomment-233071630):

Como você provavelmente sabe, você não está preso a modelos oficiais. Isso lhe dá liberdade, mas ao mesmo tempo faz com que você precise tomar mais decisões sozinho.

Acho que no final tudo é apenas um metro de equilíbrio. Quantas dessas decisões podemos tomar antecipadamente para todos (a maioria) de nossos usuários e quantas ou quais os usuários desejam tomar por conta própria.

Eu concordo com essa filosofia, mas não é a mesma atitude que encontrei sobre _esta_ questão, estranhamente. O contraste que vejo entre esse comentário e os comentários aqui se resume à liberdade. Você está retirando escolhas com base em, embora boas, intenções errôneas.

Se você realmente quer isso, não é tão difícil implementá-lo como um plugin.

@ yyx990803 Isso é provavelmente o que _Eu vou_ acabar fazendo ... provavelmente.

@LinusBorg também:

Portanto, tentamos direcionar os usuários para os pactos que achamos que funcionam melhor, enquanto deixamos uma maneira de contorná-los com o método "barramento global".

Você não está "tentando guiar", você está forçando. :)

Você tentou implementar o mesmo recurso com os métodos dispatch e EventBus?
Pode ajudar

@posva Eu planejo, mas quero dizer, você basicamente declara o objeto de barramento de evento em algum módulo e o importa para onde quiser $emit , não? Eu não gosto disso, tbh. Definitivamente vou usá-lo para algumas coisas, mas acredito fortemente que não é o que quero fazer todas as vezes.

Em qualquer caso, eu simplesmente não entendo por que isso é uma preocupação para a equipe VueJS. Se as pessoas não podem ser cuidadosas o suficiente ao usar $dispatch ,

Bem, a questão é que ninguém na equipe poderia apontar um caso de uso da vida real para $dispatch() em que fosse preferível a outras soluções (não apenas $emit() , mas também um ônibus, ou estado global), e não vimos nenhuma nas incontáveis ​​postagens sobre o assunto que respondemos.

Esta pode ser uma visão subjetiva, mas talvez você possa entender que se toda a equipe pensa "esta é, em nossa experiência, sempre uma solução inferior", nós a abandonamos por completo.

Neste ponto, quero renovar minha oferta para discutir um exemplo real.

Tenho certeza de que você pode encontrar muitas outras coisas que eles estão fazendo de errado ao usar sua biblioteca. Até onde você irá para "proteger" seus usuários de serem descuidados?

Esta é uma questão delicada e difícil de encontrar. Teremos que julgar caso a caso.

Isso é bom quando o pai tem apenas um filho direto - mas, nesse caso, $ emit () com um ouvinte no modelo também não é um trabalho extra real.

Pergunta honesta (como sou decididamente novo no Vue), além de declarar ouvintes em todos os níveis, você também não precisa $ emitir o evento em todos os componentes da cadeia? Isso parece tão irritante.

Como eu falo sobre relacionamentos diretos entre pais e filhos, você só teria que $ emit () uma vez.

Se você tem filhos aninhados profundamente, é claro que terá que reemitir em todos os níveis, mas me repito: não encontramos nem foram apresentadas situações que despacham em muitos filhos aninhados é realmente necessário ou preferível a outras soluções.

Portanto, tentamos direcionar os usuários para os pactos que achamos que funcionam melhor, enquanto deixamos uma maneira de contorná-los com o método "barramento global".

Você não está "tentando guiar", você está forçando. :)

Eu diria que tornamos sua vida um pouco mais difícil - você pode

  • usar um ônibus, que não é a mesma coisa, mas pode atingir um comportamento semelhante na maioria dos casos.
  • reimplemente isso como um plugin com bastante facilidade.

Não estamos forçando você a usar $emit() , estamos apenas tornando seu caminho um pouco mais difícil.

Acho que você também pode adicioná-lo a cada instância do Vue: Vue.prototype.$bus = new Vue()
Não gostar de algo não é muito construtivo ...
Estarei esperando seus exemplos 😄

@posva

Acho que você também pode adicioná-lo a cada instância do Vue: Vue.prototype. $ Bus = new Vue ()

Eu gosto disso. Muito inteligente.

Não gostar de algo não é muito construtivo

Acho que é um critério bastante válido para escolher usar algo ou não, pelo menos para mim. De qualquer forma, já afirmei muitas vezes por que acho que o borbulhar de eventos tem seu lugar.

Estarei esperando seus exemplos 😄

Quer dizer, eu realmente preciso? Dei exemplos de situações em que não gosto da ideia de usar um barramento de eventos ou declarar ouvintes em todos os níveis. Você quer ver o código? Eu poderia talvez inventar algo para deixar meu ponto um pouco mais claro, mas sinto que o borbulhar de eventos é uma coisa bastante padrão que a maioria das pessoas pode apreciar como algo útil, e ônibus de eventos ou gerentes estaduais são, pelo menos para mim, uma espécie de mudança de paradigma que, embora não seja difícil de compreender, parece um território hipster. 😄

É claro que estou brincando sobre o último comentário. Como afirmei antes, vejo seus usos e definitivamente encontrarei um problema para resolver com eles. Na verdade, em alguns projetos em que trabalhei usando o Ember, tendo a escrever um "serviço" que atua exatamente como um gerente de estado global. Garanto a você, não estou tentando ser teimoso sobre isso de propósito.

Eu realmente gosto do Vue. Eu só quero _adorar_, sabe?

você também não tem que $ emitir o evento em cada componente

Você o faz se pensar em termos de borbulhamento de eventos. E não o fará se usar composição de componentes.

Por exemplo:

<div>
  <a-button @click="modalShown = true">Open modal</a-button>
  <a-modal v-if="modalShown">
    <a-button @click="modalShown = false">Close modal</a-button>
  </a-modal>
</div>

a-modal componente a-button , porque ambas as instâncias a-modal e duas a-button são "filhos lógicos diretos" de uma única instância , apesar de ter uma hierarquia de visualização complicada com aninhamento.

Acho que estou apenas me repetindo neste ponto. Vou acabar resolvendo esse problema, de alguma forma. Só me parece estranho que esta discussão tenha girado em torno de declarar várias soluções alternativas para algo bastante padrão e prático que simplesmente não existe mais por qualquer motivo.

@LinusBorg :

Bem, a questão é que ninguém na equipe poderia apontar um caso de uso da vida real para $ dispatch () em que fosse preferível a outras soluções (não apenas $ emit ()

Isso me soa como um engenheiro civil me pedindo um motivo para não fechar uma saída de rodovia:

Ele diz algo como: "Esta rampa de acesso leva a um cruzamento onde as pessoas ficam confusas sobre virar à esquerda ou à direita. A maioria das pessoas conhece o caminho porque vive aqui há anos, mas novos cidadãos geralmente se perdem por alguns minutos e queremos evitar isso. "

Eu digo: "Tudo bem, claro, você pode fechá-lo, tudo bem. Vou ter que viajar 10 km adiante até a próxima rampa de saída. Vou cuidar disso."

:) Obrigado a todos pelas suas respostas. Estou feliz que vocês estejam abertos para discussão, pelo menos. Parece uma boa equipe.

Isso me soa como um engenheiro civil me pedindo um motivo para não fechar uma saída de rodovia:

Ele diz algo como: "Esta rampa de acesso leva a um cruzamento onde as pessoas ficam confusas sobre virar à esquerda ou à direita. A maioria das pessoas conhece o caminho porque vive aqui há anos, mas novos cidadãos geralmente se perdem por alguns minutos e queremos evitar isso. "

Vou adicionar meu methaphor ruim também. :) Na minha opinião, é mais como:

  • "Esta estrada incentiva as pessoas a correrem mais rápido do que deveriam. Os limites de velocidade raramente são levados em consideração. Devemos adicionar alguns pára-choques para forçar as pessoas a reduzir a velocidade."
  • "Mas eu gosto de chegar ao meu destino rapidamente em alta velocidade!"
  • "Claro, isso pode servir para você algumas vezes, mas observamos esta parte da estrada constantemente por mais de 1,5 anos, e a quantidade de acidentes e pessoas perdendo a próxima rampa de saída simplesmente não vale a pena, como muitos motoristas que tiveram um desses problemas atestou. "
  • "Mas eu não gosto desses pára-choques!"
  • Bem, para 99% dos destinos, esta outra estrada é tão rápida quanto esta era antes dos pára-choques, basta seguir por esta.
  • "Mas eu não _gosto_ dessa outra estrada! A vista não é tão boa!"
  • ...

Não gostar de algo não é muito construtivo

Acho que é um critério bastante válido para escolher usar algo ou não, pelo menos para mim. De qualquer forma, já afirmei muitas vezes por que acho que o borbulhar de eventos tem seu lugar.

Eu acho que @posva quis dizer: "Eu gosto disso" não é um argumento construtivo quando discutimos nós ou para manter algo, ou adicionar algo à biblioteca com uma ampla gama de usuários. É por isso que continuo pedindo um caso de uso válido da vida real para discutir, em vez de preferências pessoais.

Sim, exceto que você explodiu a rodovia perfeitamente boa e construiu outra com asfalto emborrachado porque você leu em algum lugar que é muito legal. Além disso, são 10 km extras. :)

Sobre o exemplo: acho que o postado na pergunta original sobre componentes recursivos está ok. Imagine que você deseja fazer algo em todos os níveis em sequência quando um evento é detectado e você tem um exemplo perfeitamente bom. Fazer isso com $ dispatch é bastante simples.

Você quer ver o código?

Sim por favor

@posva Eu dei um exemplo no comentário anterior. Nota: se você tiver que pensar mais do que alguns segundos em como fazer isso sem $ dispatch, isso prova meu ponto.

Sobre o exemplo: acho que o postado na pergunta original sobre componentes recursivos está ok. Imagine que você deseja fazer algo em todos os níveis em sequência quando um evento é detectado e você tem um exemplo perfeitamente bom. Fazer isso com $ dispatch é bastante simples.

com $dispatch()

// recursive-child
<template>
  <recursive-child></recursive-child>
  <button @click="dispatch">Do something</button>
<template>

<script>
  export default{
    methods: {
      dispatch() { this.$dispatch('do-something') }
    },
    events: {
      'do-something': function () { 
         // do something, or don't
         return true // nessessary to make the event bubble up further. Don't like the un-expressivness of this
       }
    }
  }
</script>

com $emit()

// recursive-child
<template>
  <recursive-child @do-something="doSomething"></recursive-child>
  <button @click="doSometing">Do something</button>
<template>

<script>
  export default{
    methods: {
      doSomething() {
        // do someting, or don't
        this.$emit('do-something')
      }
    }
  }
</script>

Isso é realmente pior?

Tem outro? :)

OK, claro. E se eles não forem recursivos, mas ainda assim aninhados?

Tudo bem. São 5 da manhã aqui e terei um dia difícil graças a você. Se eu vier com algo melhor depois vou postar. Do contrário, ou você ganhou ou perdi o interesse :)

E se eles não forem recursivos, mas ainda assim aninhados?

Você teria que adicionar um ouvinte @event= em cada modelo para $emit() , e não para $dispatch() , só isso.

Isso pode ser visto como bom ou ruim, dependendo de como você enfatiza a verbosidade versus a expressividade.

e btw. se em uma situação você tiver que encadear um evento até o pai, isso pode ser feito da seguinte forma:

<child-comp @event="$emit('event', $arguments)>
  • Você lamentará o "acoplamento" que isso ocorre entre os componentes.
  • Vou elogiar a expressividade
  • Fora isso, é um pouco mais para digitar, mas não é grande coisa.
  • e ainda afirmo, com um exemplo de caso de uso real, provavelmente há uma otimização diferente disponível, como uma loja global - mas isso depende do cenário individual e é difícil argumentar com o código de exemplo.

De qualquer forma, boa discussão, aproveite seu merecido sono.

@rhyek , parecem soluções alternativas apenas porque você determinou usar $dispatch em primeiro lugar, mas esse não é o objetivo. O objetivo é permitir que os componentes se comuniquem uns com os outros com uma manutenção decente. Ao atingir essa meta, $dispatch é a solução inferior quando você lista todos os prós e contras práticos, excluindo as preferências, então nós o abandonamos.

Observe também que o bubbling de eventos DOM é fundamentalmente diferente da comunicação entre componentes. O argumento de que "o borbulhamento de eventos é amplamente reconhecido" não significa que deva ser uma boa solução para o problema que estamos tentando resolver.

Parei de comentar neste tópico porque acho difícil argumentar com "Eu simplesmente não gosto disso".

Esta página foi útil?
0 / 5 - 0 avaliações