Passaggio di dati ai componenti in vue.js


92

Faccio fatica a capire come passare i dati tra i componenti in vue.js. Ho letto i documenti diverse volte e ho esaminato molte domande e tutorial relativi a vue, ma ancora non l'ho capito.

Per concludere, spero in aiuto per completare un esempio piuttosto semplice

  1. visualizzare un elenco di utenti in un componente (fatto)
  2. inviare i dati utente a un nuovo componente quando si fa clic su un collegamento (fatto) - vedere l'aggiornamento in fondo.
  3. modificare i dati utente e inviarli di nuovo al componente originale (non sono arrivato a questo punto)

Ecco un violino, che fallisce nel secondo passaggio: https://jsfiddle.net/retrogradeMT/d1a8hps0/

Capisco che devo usare gli oggetti di scena per passare i dati al nuovo componente, ma non sono sicuro di come farlo funzionalmente. Come lego i dati al nuovo 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 per il componente principale:

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 per il secondo componente:

Vue.component('newtemp', {
  template: '#newtemp',
  props: 'name',
  data: function() {
    return {
        name: name,
        }
   },
})

AGGIORNARE

Ok, ho capito il secondo passaggio. Ecco un nuovo violino che mostra i progressi: https://jsfiddle.net/retrogradeMT/9pffnmjp/

Poiché sto usando Vue-router, non uso props per inviare i dati a un nuovo componente. Invece, ho bisogno di impostare i parametri sul v-link e quindi utilizzare un hook di transizione per accettarlo.

Le modifiche al V-link vedono le rotte denominate nei documenti di vue-router :

<a v-link="{ name: 'new', params: { name: user.name }}"> Show new component</a>

Quindi sul componente, aggiungi dati alle opzioni di percorso vedi ganci di transizione :

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,
        }
   },
})

Risposte:


46

------------- Quanto segue è applicabile solo a Vue 1 --------------

Il passaggio dei dati può essere eseguito in diversi modi. Il metodo dipende dal tipo di utilizzo.


Se vuoi passare dati dal tuo html mentre aggiungi un nuovo componente. Questo viene fatto usando oggetti di scena.

<my-component prop-name="value"></my-component>

Questo valore prop sarà disponibile per il tuo componente solo se aggiungi il nome prop prop-nameal tuo propsattributo.


Quando i dati vengono passati da un componente a un altro a causa di un evento dinamico o statico. Ciò viene fatto utilizzando i dispatcher di eventi e le emittenti. Quindi, ad esempio, se hai una struttura di componenti come questa:

<my-parent>
    <my-child-A></my-child-A>
    <my-child-B></my-child-B>
</my-parent>

E vuoi inviare dati da <my-child-A>a <my-child-B>allora <my-child-A>dovrai inviare un evento:

this.$dispatch('event_name', data);

Questo evento viaggerà lungo tutta la catena principale. E da qualunque genitore tu abbia un ramo verso di <my-child-B>te trasmetti l'evento insieme ai dati. Quindi nel genitore:

events:{
    'event_name' : function(data){
        this.$broadcast('event_name', data);
    },

Ora questa trasmissione viaggerà lungo la catena del bambino. E a qualsiasi bambino tu voglia prendere l'evento, nel nostro caso <my-child-B>aggiungeremo un altro evento:

events: {
    'event_name' : function(data){
        // Your code. 
    },
},

Il terzo modo per passare i dati è attraverso i parametri nei v-link. Questo metodo viene utilizzato quando le catene di componenti vengono completamente distrutte o nei casi in cui l'URI cambia. E vedo che li capisci già.


Decidi che tipo di comunicazione di dati desideri e scegli in modo appropriato.


1
Grazie, è stato davvero utile. L'unico pezzo con cui sto ancora lottando sono le convenzioni sui nomi. cioè: ho user.name che passo tramite v-link come nome. Ora posso modificare la variabile name e passarla di nuovo al componente originale come nome, ma il componente originale non ha una variabile chiamata nome. Cosa mi manca qui? Non sembra possibile far passare un oggetto tramite v-link?
retrogrado

1
Stai già passando un oggetto. paramsè un oggetto. La chiave del nome può essere assegnata this.user.namenel componente. Crea un violino se hai bisogno di aiuto e fammi sapere. Controlla questo: vuejs.github.io/vue-router/en/route.html
notANerdDev

Ah, ok ora ce l'ho. Grazie ancora. Apprezzo il tuo aiuto, ha davvero reso le cose molto più chiare.
retrogrado

6
Risposta fantastica ma da quanto ho capito non funzionerà con 2.0 poiché gli eventi sono stati deprecati?
rix

2
Ho adorato la risposta ma poi sono arrivato ai commenti e dato che sto lavorando con Vue 2, sento che non sarò in grado di utilizzare il secondo metodo suggerito da te. È correttamente temuto?
Konrad Viltersten

23

Il modo migliore per inviare dati da un componente genitore a un bambino è usare oggetti di scena .

Passaggio di dati da genitore a figlio tramite props

  • Dichiarare props(array o oggetto ) nel bambino
  • Passalo al bambino tramite <child :name="variableOnParent">

Guarda la demo di seguito:

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/vue@2.5.13/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>


piccola correzione: "<child-comp" invece di "<child" e variableAtParent .. Passalo al bambino tramite <child-comp: name = "variableAtParent">
muenalan

Funzionerà solo con proprietà semplici, i riferimenti agli oggetti non verranno aggiornati. Ad esempio, se la proprietà genitore è array e questo array è stato sostituito nell'oggetto genitore con un altro array, il figlio non lo vedrà.
Stan Sokolov

@StanSokolov per niente. Lavoro per gli array, vedi: jsfiddle.net/acdcjunior/q4mank05 . Se l'array non è reattivo, probabilmente stai affrontando un problema di reattività. Prova a usarne diVue.set più qui: vuejs.org/v2/guide/reactivity.html#For-Arrays
acdcjunior

Che senso ha se non è reattivo? Certo era reattivo con riferimento costantemente sostituito da un nuovo array. Vue non propaga "modifiche di riferimento" ai bambini, ma solo modifiche di valore su elementi semplici. Quindi, se il riferimento all'array è stato sovrascritto in parent, i figli vedranno ancora il vecchio riferimento. Non saprà mai che il genitore ora lavora con un oggetto diverso.
Stan Sokolov,

@StanSokolov Vedi questo: jsfiddle.net/acdcjunior/ftmrne2h l'array viene sostituito nel genitore e il bambino lo vede / reagisce (fai clic sul pulsante per testare). O intendi qualcos'altro? In tal caso, sarebbe utile se modifichi il violino per mostrarlo
acdcjunior

15

Penso che il problema sia qui:

<template id="newtemp" :name ="{{user.name}}">

Quando prefissi il puntello con :stai indicando a Vue che è una variabile, non una stringa. Quindi non hai bisogno del {{}}giro user.name. Provare:

<template id="newtemp" :name ="user.name">

MODIFICARE-----

Quanto sopra è vero, ma il problema più grande qui è che quando si cambia l'URL e si passa a un nuovo percorso, il componente originale scompare. Affinché il secondo componente modifichi i dati padre, il secondo componente dovrebbe essere un componente figlio del primo o solo una parte dello stesso componente.


Grazie jeff. Ho provato a rimuovere {{}} ma ricevo ancora gli stessi errori.
retrogrado

2

Ho trovato un modo per passare i dati genitore all'ambito del componente in Vue, penso che sia un po 'un trucco ma forse questo ti aiuterà.

1) Dati di riferimento nell'istanza Vue come oggetto esterno (data : dataObj)

2) Quindi nella funzione di restituzione dei dati nel componente figlio basta tornare parentScope = dataObje voilà. Ora non puoi fare cose simili {{ parentScope.prop }}e funzionerà come un incantesimo.

In bocca al lupo!


Questo è accoppiare entrambi i componenti insieme ciò che può andare bene per un albero e i suoi nodi, ma normalmente non è favorito. Proverei ad evitarlo.
dicembre

1

Le risposte sopra menzionate funzionano bene, ma se si desidera trasferire i dati tra 2 componenti di pari livello, è possibile utilizzare anche il bus degli eventi. Dai un'occhiata a questo blog che ti aiuterebbe a capire meglio.

Supponiamo per 2 componenti: CompA e CompB che hanno lo stesso genitore e main.js per la configurazione dell'app vue principale. Per passare dati da CompA a CompB senza coinvolgere il componente principale, è possibile eseguire le seguenti operazioni.

nel file main.js, dichiara un'istanza di Vue globale separata, che sarà il bus degli eventi.

export const bus = new Vue();

In CompA, dove viene generato l'evento: devi emettere l'evento sul bus.

methods: {
      somethingHappened (){
          bus.$emit('changedSomething', 'new data');
      }
  }

Ora il compito è ascoltare l'evento emesso, quindi, in CompB, puoi ascoltare come.

created (){
    bus.$on('changedSomething', (newData) => {
      console.log(newData);
    })
  }

Vantaggi:

  • Codice meno e pulito.
  • Il genitore non dovrebbe coinvolgere la trasmissione dei dati da 1 comp figlio a un altro (man mano che il numero di bambini cresce, diventerà difficile mantenerlo)
  • Segue l'approccio pub-sub.

0

Accedo alle proprietà principali utilizzando $root.

Vue.component("example", { 
    template: `<div>$root.message</div>`
});
...
<example></example>

-2

Una variabile JS globale (oggetto) può essere utilizzata per passare i dati tra i componenti. Esempio: passaggio di dati da Ammlogin.vue a Options.vue. In Ammlogin.vue rspData è impostato sulla risposta del server. In Options.vue la risposta dal server è resa disponibile tramite 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>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.