Estou lutando para entender como transmitir dados entre componentes em vue.js. Eu li a documentação várias vezes e olhei muitas perguntas e tutoriais relacionados, mas ainda não estou entendendo.
Para entender isso, espero ajuda para completar um exemplo bem simples
- exibir uma lista de usuários em um componente (pronto)
- enviar os dados do usuário para um novo componente quando um link for clicado (concluído) - consulte a atualização na parte inferior.
- edite os dados do usuário e envie-os de volta ao componente original (não cheguei até aqui)
Aqui está um violino, que falha na etapa dois: https://jsfiddle.net/retrogradeMT/d1a8hps0/
Eu entendo que preciso usar adereços para passar dados para o novo componente, mas não tenho certeza de como fazer isso funcionalmente. Como vinculo os dados ao novo componente?
HTML:
<div id="page-content">
<router-view></router-view>
</div>
<template id="userBlock" >
<ul>
<li v-for="user in users">{{user.name}} - <a v-link="{ path: '/new' }"> Show new component</a>
</li>
</ul>
</template>
<template id="newtemp" :name ="{{user.name}}">
<form>
<label>Name: </label><input v-model="name">
<input type="submit" value="Submit">
</form>
</template>
js para o componente principal:
Vue.component('app-page', {
template: '#userBlock',
data: function() {
return{
users: []
}
},
ready: function () {
this.fetchUsers();
},
methods: {
fetchUsers: function(){
var users = [
{
id: 1,
name: 'tom'
},
{
id: 2,
name: 'brian'
},
{
id: 3,
name: 'sam'
},
];
this.$set('users', users);
}
}
})
JS para o segundo componente:
Vue.component('newtemp', {
template: '#newtemp',
props: 'name',
data: function() {
return {
name: name,
}
},
})
ATUALIZAR
Ok, eu descobri a segunda etapa. Aqui está um novo violino mostrando o progresso: https://jsfiddle.net/retrogradeMT/9pffnmjp/
Como estou usando o Vue-router, não uso props para enviar os dados para um novo componente. Em vez disso, preciso definir parâmetros no v-link e usar um gancho de transição para aceitá-lo.
As alterações do V-link, consulte as rotas nomeadas nos documentos do vue-router :
<a v-link="{ name: 'new', params: { name: user.name }}"> Show new component</a>
Em seguida, no componente, adicione dados às opções de rota, consulte os ganchos de transição :
Vue.component('newtemp', {
template: '#newtemp',
route: {
data: function(transition) {
transition.next({
// saving the id which is passed in url
name: transition.to.params.name
});
}
},
data: function() {
return {
name:name,
}
},
})
fonte
params
é um objeto. A chave do nome pode ser atribuídathis.user.name
em seu componente. Crie um violino se precisar de ajuda e me avise. Verifique isso: vuejs.github.io/vue-router/en/route.htmlA melhor maneira de enviar dados de um componente pai para um filho é usando adereços .
Passando dados de pais para filhos via
props
props
(matriz ou objeto ) no filho<child :name="variableOnParent">
Veja a demonstração abaixo:
Vue.component('child-comp', { props: ['message'], // declare the props template: '<p>At child-comp, using props in the template: {{ message }}</p>', mounted: function () { console.log('The props are also available in JS:', this.message); } }) new Vue({ el: '#app', data: { variableAtParent: 'DATA FROM PARENT!' } })
<script src="https://unpkg.com/[email protected]/dist/vue.min.js"></script> <div id="app"> <p>At Parent: {{ variableAtParent }}<br>And is reactive (edit it) <input v-model="variableAtParent"></p> <child-comp :message="variableAtParent"></child-comp> </div>
fonte
Vue.set
, mais aqui: vuejs.org/v2/guide/reactivity.html#For-ArraysAcho que o problema está aqui:
<template id="newtemp" :name ="{{user.name}}">
Quando você prefixa o prop com,
:
está indicando ao Vue que é uma variável, não uma string. Então você não precisa da{{}}
voltauser.name
. Experimentar:<template id="newtemp" :name ="user.name">
EDITAR-----
O que foi dito acima é verdade, mas o maior problema aqui é que quando você altera a URL e vai para uma nova rota, o componente original desaparece. Para que o segundo componente edite os dados pai, o segundo componente precisará ser um componente filho do primeiro ou apenas uma parte do mesmo componente.
fonte
Eu encontrei uma maneira de passar dados pai para o escopo do componente no Vue, eu acho que é um pouco um hack, mas talvez isso ajude você.
1) Dados de referência na instância Vue como um objeto externo
(data : dataObj)
2) Então, na função de retorno de dados no componente filho, apenas retorne
parentScope = dataObj
e voila. Agora você não pode fazer coisas como{{ parentScope.prop }}
e vai funcionar como um encanto.Boa sorte!
fonte
As respostas mencionadas acima funcionam bem, mas se você quiser passar dados entre 2 componentes irmãos, o barramento de eventos também pode ser usado. Confira este blog que o ajudará a entender melhor.
suponha para 2 componentes: CompA e CompB tendo o mesmo pai e main.js para configurar o aplicativo principal. Para passar dados de CompA para CompB sem envolver o componente pai, você pode fazer o seguinte.
no arquivo main.js, declare uma instância global separada do Vue, que será o barramento de eventos.
export const bus = new Vue();
No CompA, onde o evento é gerado: você deve emitir o evento para o barramento.
methods: { somethingHappened (){ bus.$emit('changedSomething', 'new data'); } }
Agora a tarefa é ouvir o evento emitido, então, no CompB, você pode ouvir como.
created (){ bus.$on('changedSomething', (newData) => { console.log(newData); }) }
Vantagens:
fonte
Eu acesso as propriedades principais usando
$root
.Vue.component("example", { template: `<div>$root.message</div>` }); ... <example></example>
fonte
Uma variável JS global (objeto) pode ser usada para passar dados entre componentes. Exemplo: Passando dados de Ammlogin.vue para Options.vue. Em Ammlogin.vue rspData é definido para a resposta do servidor. Em Options.vue, a resposta do servidor é disponibilizada via rspData.
index.html:
<script> var rspData; // global - transfer data between components </script>
Ammlogin.vue:
.... export default { data: function() {return vueData}, methods: { login: function(event){ event.preventDefault(); // otherwise the page is submitted... vueData.errortxt = ""; axios.post('http://vueamm...../actions.php', { action: this.$data.action, user: this.$data.user, password: this.$data.password}) .then(function (response) { vueData.user = ''; vueData.password = ''; // activate v-link via JS click... // JSON.parse is not needed because it is already an object if (response.data.result === "ok") { rspData = response.data; // set global rspData document.getElementById("loginid").click(); } else { vueData.errortxt = "Felaktig avändare eller lösenord!" } }) .catch(function (error) { // Wu oh! Something went wrong vueData.errortxt = error.message; }); }, ....
Options.vue:
<template> <main-layout> <p>Alternativ</p> <p>Resultat: {{rspData.result}}</p> <p>Meddelande: {{rspData.data}}</p> <v-link href='/'>Logga ut</v-link> </main-layout> </template> <script> import MainLayout from '../layouts/Main.vue' import VLink from '../components/VLink.vue' var optData = { rspData: rspData}; // rspData is global export default { data: function() {return optData}, components: { MainLayout, VLink } } </script>
fonte