Estoy luchando por entender cómo pasar datos entre componentes en vue.js. Leí los documentos varias veces y miré muchas preguntas y tutoriales relacionados con vue, pero todavía no lo entiendo.
Para entender esto, espero recibir ayuda para completar un ejemplo bastante simple
- mostrar una lista de usuarios en un componente (hecho)
- enviar los datos del usuario a un nuevo componente cuando se hace clic en un enlace (hecho); consulte la actualización en la parte inferior.
- editar los datos del usuario y enviarlos de vuelta al componente original (no he llegado tan lejos)
Aquí hay un violín, que falla en el paso dos: https://jsfiddle.net/retrogradeMT/d1a8hps0/
Entiendo que necesito usar accesorios para pasar datos al nuevo componente, pero no estoy seguro de cómo hacerlo funcionalmente. ¿Cómo vinculo los datos al nuevo 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 el 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 el segundo componente:
Vue.component('newtemp', {
template: '#newtemp',
props: 'name',
data: function() {
return {
name: name,
}
},
})
ACTUALIZAR
Ok, ya he resuelto el segundo paso. Aquí hay un nuevo violín que muestra el progreso: https://jsfiddle.net/retrogradeMT/9pffnmjp/
Como estoy usando el enrutador Vue, no uso accesorios para enviar los datos a un nuevo componente. En su lugar, necesito establecer parámetros en el v-link y luego usar un gancho de transición para aceptarlo.
Los cambios de V-link ven las rutas con nombre en los documentos de vue-router :
<a v-link="{ name: 'new', params: { name: user.name }}"> Show new component</a>
Luego, en el componente, agregue datos a las opciones de ruta, vea los ganchos de transición :
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,
}
},
})
fuente
params
es un objeto. La clave de nombre se puede asignar athis.user.name
su componente. Crea un violín si necesitas ayuda y házmelo saber. Mira esto: vuejs.github.io/vue-router/en/route.htmlLa mejor forma de enviar datos desde un componente principal a un hijo es utilizando accesorios .
Pasar datos de padres a hijos a través de
props
props
(matriz u objeto ) en el niño<child :name="variableOnParent">
Vea la demostración a continuación:
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>
fuente
Vue.set
, más aquí: vuejs.org/v2/guide/reactivity.html#For-ArraysCreo que el problema está aquí:
<template id="newtemp" :name ="{{user.name}}">
Cuando le pone el prefijo al prop,
:
le indica a Vue que es una variable, no una cadena. Entonces no necesitas el{{}}
alrededoruser.name
. Tratar:<template id="newtemp" :name ="user.name">
EDITAR-----
Lo anterior es cierto, pero el problema más grande aquí es que cuando cambia la URL y va a una nueva ruta, el componente original desaparece. Para que el segundo componente edite los datos principales, el segundo componente debería ser un componente secundario del primero, o simplemente una parte del mismo componente.
fuente
Encontré una manera de pasar los datos de los padres al alcance del componente en Vue, creo que es un poco complicado, pero tal vez esto te ayude.
1) Datos de referencia en Vue Instance como un objeto externo
(data : dataObj)
2) Luego, en la función de retorno de datos en el componente secundario, simplemente regrese
parentScope = dataObj
y listo. Ahora no puedes hacer cosas así{{ parentScope.prop }}
y funcionarás de maravilla .¡Buena suerte!
fuente
Las respuestas mencionadas anteriormente funcionan bien, pero si desea pasar datos entre 2 componentes hermanos, también se puede utilizar el bus de eventos. Consulte este blog que lo ayudará a comprender mejor.
supongamos que para 2 componentes: CompA y CompB tienen el mismo padre y main.js para configurar la aplicación principal de vue. Para pasar datos de CompA a CompB sin involucrar el componente principal, puede hacer lo siguiente.
en el archivo main.js, declare una instancia de Vue global separada, que será el bus de eventos.
export const bus = new Vue();
En CompA, donde se genera el evento: hay que emitir el evento al bus.
methods: { somethingHappened (){ bus.$emit('changedSomething', 'new data'); } }
Ahora la tarea es escuchar el evento emitido, entonces, en CompB, puedes escuchar like.
created (){ bus.$on('changedSomething', (newData) => { console.log(newData); }) }
Ventajas:
fuente
Accedo a las propiedades principales usando
$root
.Vue.component("example", { template: `<div>$root.message</div>` }); ... <example></example>
fuente
Se puede usar una variable JS global (objeto) para pasar datos entre componentes. Ejemplo: pasar datos de Ammlogin.vue a Options.vue. En Ammlogin.vue, rspData se establece en la respuesta del servidor. En Options.vue, la respuesta del servidor está disponible a través de 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>
fuente