VueJS greift vom übergeordneten Element auf die Daten der untergeordneten Komponente zu

74

Ich benutze das Vue-Cli-Gerüst für das Webpack

Die Struktur / Hierarchie meiner Vue-Komponenten sieht derzeit folgendermaßen aus:

  • App
    • PDF-Vorlage
      • Hintergrund
      • Dynamisches Vorlagenbild
      • Statisches Vorlagenbild
      • Abschlag

Auf App-Ebene möchte ich eine vuejs-Komponentenmethode, mit der alle Daten der untergeordneten Komponente zu einem einzigen JSON-Objekt zusammengefasst werden können, das an den Server gesendet werden kann.

Gibt es eine Möglichkeit, auf die Daten der untergeordneten Komponente zuzugreifen? Insbesondere mehrere Schichten tief?

Wenn nicht, wie empfiehlt es sich, überservable Daten / Parameter weiterzugeben, damit ich bei Änderungen durch untergeordnete Komponenten auf die neuen Werte zugreifen kann? Ich versuche, harte Abhängigkeiten zwischen Komponenten zu vermeiden. Ab sofort werden nur noch Initialisierungswerte mit Komponentenattributen übergeben.

AKTUALISIEREN:

Solide Antworten. Ressourcen, die ich nach Durchsicht beider Antworten hilfreich fand:

Daniel Brown
quelle

Antworten:

52

Für diese Art von Struktur ist es gut, eine Art Geschäft zu haben.

VueJS bietet eine Lösung dafür und heißt Vuex. Wenn Sie nicht bereit sind, mit Vuex zu arbeiten, können Sie Ihren eigenen einfachen Shop erstellen.

Versuchen wir es damit

MarkdownStore.js

export default {

 data: {
   items: []
 },

 // Methods that you need, for e.g fetching data from server etc.

 fetchData() {
   // fetch logic
 }

}

Und jetzt können Sie diese Daten überall verwenden, indem Sie diese Store-Datei importieren

HomeView.vue

import MarkdownStore from '../stores/MarkdownStore'

export default {

 data() {
   sharedItems: MarkdownStore.data
 },

 created() {
   MarkdownStore.fetchData()
 }

}

Das ist also der grundlegende Ablauf, den Sie verwenden können, wenn Sie nicht mit Vuex arbeiten möchten.

Belmin Bedak
quelle
Die Dokumentation erklärt es auch ziemlich gut.
Toast
Was ist, wenn ich die Logik fetchData () in MarkdownStore verschieben möchte? Es ist sinnvoll, die gesamte Komponentenlogik in die Komponente einzufügen.
PJ3
Diese Lösung hat bei mir fast funktioniert. Ich kann auf die fetchData () -Methode zugreifen, aber diese Methode kann nicht auf die Daten in der MarkdownStore-Ansicht zugreifen. this.data.items oder this. $ data.items hat nicht funktioniert
YeeHaw1234
1
@ YeeHaw1234 Sie sollten this.itemsvon Ihrer Komponente aus darauf zugreifen .
Belmin Bedak
43

Ich bin mir nicht sicher, ob dies eine gute Praxis ist oder nicht.

In meiner untergeordneten Komponente gibt es keine Schaltflächen zum Ausgeben geänderter Daten. Es ist eine Form mit etwas 5 ~ 10 Eingaben. Die Daten werden gesendet, sobald Sie in einer anderen Komponente auf die Schaltfläche Prozess klicken. Daher kann ich nicht jede Eigenschaft ausgeben, wenn sie sich ändert.

Also, was ich getan habe,

In meiner übergeordneten Komponente kann ich über "ref" auf die Daten des Kindes zugreifen.

z.B

<markdown ref="markdowndetails"></markdown>
<app-button @submit="process"></app-button>

// js
methods:{
    process: function(){
        // items is defined object inside data()
        var markdowns = this.$refs.markdowndetails.items 
    }
}

Hinweis: Wenn Sie dies in der gesamten Anwendung tun, empfehle ich, stattdessen zu vuex zu wechseln.

PJ3
quelle
1
Wo finde ich die Dokumentation dazu?
Jujubes
3
@ Jujubes vuejs.org/v2/guide/…
xonya
Hat gut für mich funktioniert - Danke @ PJ3
Zeshan
28

Was ist die beste Vorgehensweise für die Weitergabe von überwartbaren Daten / Parametern, damit ich bei Änderungen durch untergeordnete Komponenten Zugriff auf die neuen Werte habe?

Der Fluss der Requisiten ist ein Weg nach unten. Ein Kind sollte seine Requisiten niemals direkt modifizieren.

Für eine komplexe Anwendung ist Vuex die Lösung, für einen einfachen Fall ist Vuex ein Overkill. Genau wie @Belmin gesagt hat, können Sie dafür dank des Reaktivitätssystems sogar ein einfaches JavaScript-Objekt verwenden.

Eine andere Lösung ist die Verwendung von Ereignissen. Vue hat die EventEmitter-Schnittstelle bereits implementiert, über die ein Kind this.$emit('eventName', data)mit seinem Elternteil kommunizieren kann .

Die Eltern hören dem Ereignis folgendermaßen zu: ( @updateist die Abkürzung von v-on:update)

<child :value="value" @update="onChildUpdate" />

und aktualisieren Sie die Daten im Ereignishandler:

methods: {
  onChildUpdate (newValue) {
    this.value = newValue
  }
}

Hier ist ein einfaches Beispiel für benutzerdefinierte Ereignisse in Vue:
http://codepen.io/CodinCat/pen/ZBELjm?editors=1010

Dies ist nur eine Eltern-Kind-Kommunikation. Wenn eine Komponente mit ihren Geschwistern sprechen muss, benötigen Sie einen globalen Ereignisbus. In Vue.js können Sie einfach eine leere Vue-Instanz verwenden:

const bus = new Vue()

// In component A
bus.$on('somethingUpdated', data => { ... })

// In component B
bus.$emit('somethingUpdated', newData)
CodinCat
quelle
5

Sie können sich auf die untergeordnete Komponente beziehen und diese als diese verwenden. $ refs.refComponentName. $ data

übergeordnete Komponente

<template>
   <section>
      <childComponent ref="nameOfRef" />
   </section>
</template>

 methods: {
  save() {
   let Data = this.$refs.nameOfRef.$data;
 }
},
Mohamed Adel
quelle
1

In meinem Fall habe ich ein Registrierungsformular, das ich in Komponenten unterteilt habe.

Wie oben vorgeschlagen, habe ich $ refs verwendet. Bei meinen Eltern habe ich zum Beispiel:

In Vorlage:

<Personal ref="personal" />

Skript - Übergeordnete Komponente

export default {
  components: {
    Personal,
    Employment
  },
  data() {
    return {
        personal: null,
        education: null
    }
  },
  mounted: function(){
       this.personal = this.$refs.personal.model
       this.education = this.$refs.education.model
  }
}

Dies funktioniert gut, da die Daten reaktiv sind.

louis_coetzee
quelle