Übergeben von Daten an Komponenten in vue.js.

92

Ich habe Probleme zu verstehen, wie Daten zwischen Komponenten in vue.js übertragen werden. Ich habe die Dokumente mehrmals durchgelesen und mir viele Fragen und Tutorials zum Thema Vue angesehen, aber ich verstehe sie immer noch nicht.

Um dies in den Kopf zu bekommen, hoffe ich auf Hilfe bei der Vervollständigung eines ziemlich einfachen Beispiels

  1. eine Liste der Benutzer in einer Komponente anzeigen (fertig)
  2. Senden Sie die Benutzerdaten an eine neue Komponente, wenn Sie auf einen Link klicken (fertig) - siehe Update unten.
  3. Benutzerdaten bearbeiten und an die Originalkomponente zurücksenden (noch nicht so weit)

Hier ist eine Geige, die in Schritt zwei fehlschlägt: https://jsfiddle.net/retrogradeMT/d1a8hps0/

Ich verstehe, dass ich Requisiten verwenden muss, um Daten an die neue Komponente zu übergeben, bin mir aber nicht sicher, wie ich das funktional tun soll. Wie binde ich die Daten an die neue Komponente?

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 für Hauptkomponente:

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 für die zweite Komponente:

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

AKTUALISIEREN

Ok, ich habe den zweiten Schritt herausgefunden. Hier ist eine neue Geige, die den Fortschritt zeigt: https://jsfiddle.net/retrogradeMT/9pffnmjp/

Da ich einen Vue-Router verwende, verwende ich keine Requisiten, um die Daten an eine neue Komponente zu senden. Stattdessen muss ich Parameter für den V-Link festlegen und dann einen Übergangshaken verwenden, um ihn zu akzeptieren.

V-Link-Änderungen siehe benannte Routen in den Vue-Router-Dokumenten :

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

Fügen Sie dann auf der Komponente Daten zu den Routenoptionen hinzu, siehe Übergangshooks :

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,
        }
   },
})
rückläufig
quelle

Antworten:

45

------------- Das Folgende gilt nur für Vue 1 --------------

Das Übergeben von Daten kann auf verschiedene Arten erfolgen. Die Methode hängt von der Art der Verwendung ab.


Wenn Sie Daten aus Ihrem HTML-Code übergeben möchten, während Sie eine neue Komponente hinzufügen. Dies geschieht mit Requisiten.

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

Dieser Requisitenwert steht Ihrer Komponente nur zur Verfügung, wenn Sie prop-nameIhrem propsAttribut den Requisitennamen hinzufügen .


Wenn Daten aufgrund eines dynamischen oder statischen Ereignisses von einer Komponente an eine andere Komponente übergeben werden. Dies geschieht mithilfe von Event-Dispatchern und Sendern. Wenn Sie beispielsweise eine Komponentenstruktur wie diese haben:

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

Und wenn Sie Daten von <my-child-A>bis <my-child-B>dahin senden möchten, müssen <my-child-A>Sie ein Ereignis auslösen:

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

Dieses Ereignis wird sich über die gesamte Elternkette erstrecken. Und von jedem Elternteil, zu dem Sie einen Zweig haben <my-child-B>, senden Sie das Ereignis zusammen mit den Daten. Also im Elternteil:

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

Jetzt wird diese Sendung die Kinderkette entlang laufen. Und bei jedem Kind, an dem Sie teilnehmen möchten, <my-child-B>fügen wir in unserem Fall ein weiteres Ereignis hinzu:

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

Die dritte Möglichkeit, Daten zu übergeben, besteht in Parametern in V-Links. Diese Methode wird verwendet, wenn Komponentenketten vollständig zerstört werden oder wenn sich der URI ändert. Und ich kann sehen, dass du sie bereits verstehst.


Entscheiden Sie, welche Art von Datenkommunikation Sie möchten, und wählen Sie sie entsprechend aus.

notANerdDev
quelle
Danke, das war wirklich hilfreich. Das einzige Stück, mit dem ich noch zu kämpfen habe, sind Namenskonventionen. dh: Ich habe user.name, den ich über v-link als name übergebe. Ich kann jetzt die Namensvariable bearbeiten und als Name an die ursprüngliche Komponente zurückgeben, aber die ursprüngliche Komponente hat keine Variable namens name. Was vermisse ich hier? Scheint es nicht möglich zu sein, ein Objekt über v-link zu übergeben?
Rückschritt
1
Sie übergeben bereits ein Objekt. paramsist ein Objekt. Der Namensschlüssel kann this.user.namein Ihrer Komponente zugewiesen werden. Erstellen Sie eine Geige, wenn Sie Hilfe benötigen, und lassen Sie es mich wissen. Überprüfen Sie dies heraus: vuejs.github.io/vue-router/en/route.html
notANerdDev
Ah, ok, ich habe es jetzt. Danke noch einmal. Ich schätze Ihre Hilfe, sie hat die Dinge wirklich viel klarer gemacht.
Rückschritt
6
Tolle Antwort, aber wie ich verstehe, wird es mit 2.0 nicht funktionieren, da Ereignisse veraltet sind?
Rix
2
Ich habe die Antwort geliebt, bin dann aber zu den Kommentaren gekommen und da ich mit Vue 2 arbeite, habe ich das Gefühl, dass ich die von Ihnen vorgeschlagene zweite Methode nicht anwenden kann. Ist das richtig gefürchtet?
Konrad Viltersten
20

Der beste Weg, um Daten von einer übergeordneten Komponente an ein untergeordnetes Element zu senden, ist die Verwendung von Requisiten .

Übergabe von Daten vom Elternteil an das Kind über props

  • Deklarieren props(Array oder Objekt ) im Kind
  • Geben Sie es über an das Kind weiter <child :name="variableOnParent">

Siehe Demo unten:

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>

acdcjunior
quelle
kleiner Fix: "<child-comp" anstelle von "<child" und variableAtParent. Übergeben Sie es an das Kind über <child-comp: name = "variableAtParent">
muenalan
Es funktioniert nur mit einfachen Eigenschaften, Objektreferenzen werden nicht aktualisiert. Wenn Sie beispielsweise die übergeordnete Eigenschaft Array haben und dieses Array im übergeordneten Objekt durch ein anderes Array ersetzt wurde, wird es von Child nicht angezeigt.
Stan Sokolov
@ StanSokolov überhaupt nicht. Ich arbeite für Arrays, siehe: jsfiddle.net/acdcjunior/q4mank05 . Wenn Ihr Array nicht reaktiv ist, liegt wahrscheinlich ein Reaktivitätsproblem vor. Versuchen Sie es mit Vue.setmehr hier: vuejs.org/v2/guide/reactivity.html#For-Arrays
acdcjunior
Was ist der Sinn, wenn es nicht reaktiv ist? Sicher war es reaktiv mit Referenz, die ständig durch ein neues Array ersetzt wurde. Vue gibt keine "Referenzänderungen" an untergeordnete Elemente weiter, sondern nur Wertänderungen an einfachen Elementen. Wenn also der Verweis auf das Array im übergeordneten Element überschrieben wurde, wird den Kindern der alte Verweis weiterhin angezeigt. Ich werde nie erfahren, dass Eltern jetzt mit einem anderen Objekt arbeiten.
Stan Sokolov
@StanSokolov Siehe dies: jsfiddle.net/acdcjunior/ftmrne2h Das Array wird im übergeordneten Array ersetzt und das Kind sieht / reagiert darauf (klicken Sie zum Testen auf die Schaltfläche). Oder meinst du etwas anderes? Wenn ja, wäre es hilfreich, wenn Sie die Geige bearbeiten, um sie
anzuzeigen
15

Ich denke, das Problem ist hier:

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

Wenn Sie der Requisite ein Präfix voranstellen, zeigen :Sie Vue an, dass es sich um eine Variable und nicht um eine Zeichenfolge handelt. Sie brauchen also nicht die {{}}Umgebung user.name. Versuchen:

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

BEARBEITEN-----

Das Obige ist wahr, aber das größere Problem hierbei ist, dass die ursprüngliche Komponente verschwindet, wenn Sie die URL ändern und zu einer neuen Route wechseln. Damit die zweite Komponente die übergeordneten Daten bearbeitet, muss die zweite Komponente eine untergeordnete Komponente der ersten oder nur ein Teil derselben Komponente sein.

Jeff
quelle
Danke jeff. Ich habe versucht, das {{}} zu entfernen, erhalte aber immer noch die gleichen Fehler.
Rückschritt
2

Ich habe einen Weg gefunden, übergeordnete Daten an den Komponentenbereich in Vue zu übergeben. Ich denke, es ist ein kleiner Hack, aber vielleicht hilft Ihnen das.

1) Referenzdaten in Vue Instance als externes Objekt (data : dataObj)

2) Dann in der Datenrückgabefunktion in der parentScope = dataObjuntergeordneten Komponente einfach zurück und voila. Jetzt können Sie Dinge wie tun {{ parentScope.prop }}und werden wie ein Zauber arbeiten.

Viel Glück!

Lucas Serena
quelle
Das koppelt beide Komponenten miteinander, was für einen Baum und seine Knoten in Ordnung sein kann, wird aber normalerweise nicht bevorzugt. Ich würde versuchen, dies zu vermeiden.
Dezember
1

Die oben genannten Antworten funktionieren gut, aber wenn Sie Daten zwischen zwei Geschwisterkomponenten übertragen möchten, kann auch der Ereignisbus verwendet werden. Schauen Sie sich diesen Blog an, der Ihnen helfen würde, besser zu verstehen.

Angenommen, es handelt sich um zwei Komponenten: CompA und CompB mit demselben übergeordneten und demselben main.js zum Einrichten der Haupt-Vue-App. Um Daten von CompA an CompB zu übergeben, ohne die übergeordnete Komponente einzubeziehen, haben Sie folgende Möglichkeiten.

Deklarieren Sie in der Datei main.js eine separate globale Vue-Instanz, die als Ereignisbus fungiert.

export const bus = new Vue();

In CompA, wo das Ereignis generiert wird: Sie müssen das Ereignis an den Bus senden.

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

Jetzt besteht die Aufgabe darin, das ausgegebene Ereignis abzuhören, sodass Sie in CompB wie zuhören können.

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

Vorteile:

  • Weniger & sauberer Code.
  • Eltern sollten nicht daran beteiligt sein, Daten von einem Kind an ein anderes weiterzugeben (da die Anzahl der Kinder zunimmt, wird es schwierig, sie zu pflegen).
  • Folgt dem Pub-Sub-Ansatz.
Divesh Sahu
quelle
0

Ich greife mit auf die Haupteigenschaften zu $root.

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

Eine globale JS-Variable (Objekt) kann verwendet werden, um Daten zwischen Komponenten zu übertragen. Beispiel: Übergeben von Daten von Ammlogin.vue an Options.vue. In Ammlogin.vue wird rspData auf die Antwort vom Server festgelegt. In Options.vue wird die Antwort vom Server über rspData verfügbar gemacht.

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>
Kjelle J.
quelle