Meneruskan data ke komponen di vue.js

92

Saya kesulitan memahami cara melewatkan data antar komponen di vue.js. Saya telah membaca dokumen beberapa kali dan melihat banyak pertanyaan dan tutorial yang berhubungan dengan vue, tetapi saya masih belum mengerti.

Untuk menyelesaikan masalah ini, saya mengharapkan bantuan untuk menyelesaikan contoh yang cukup sederhana

  1. menampilkan daftar pengguna dalam satu komponen (selesai)
  2. mengirim data pengguna ke komponen baru ketika tautan diklik (selesai) - lihat pembaruan di bagian bawah.
  3. edit data pengguna dan kirim kembali ke komponen asli (belum sampai sejauh ini)

Ini biola, yang gagal pada langkah kedua: https://jsfiddle.net/retrogradeMT/d1a8hps0/

Saya memahami bahwa saya perlu menggunakan alat peraga untuk mengirimkan data ke komponen baru, tetapi saya tidak yakin bagaimana cara melakukannya secara fungsional. Bagaimana cara mengikat data ke komponen baru?

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 untuk komponen utama:

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 untuk komponen kedua:

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

MEMPERBARUI

Oke, saya sudah mengetahui langkah kedua. Ini biola baru yang menunjukkan kemajuan: https://jsfiddle.net/retrogradeMT/9pffnmjp/

Karena saya menggunakan Vue-router, saya tidak menggunakan props untuk mengirim data ke komponen baru. Sebagai gantinya, saya perlu mengatur params pada v-link dan kemudian menggunakan hook transisi untuk menerimanya.

Perubahan V-link lihat rute bernama di dokumen vue-router :

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

Kemudian pada komponen, tambahkan data ke opsi rute, lihat pengait transisi :

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

Jawaban:

46

------------- Berikut ini hanya berlaku untuk Vue 1 --------------

Penyampaian data dapat dilakukan dengan berbagai cara. Metodenya tergantung pada jenis penggunaan.


Jika Anda ingin meneruskan data dari html Anda saat Anda menambahkan komponen baru. Itu dilakukan dengan menggunakan alat peraga.

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

Nilai prop ini akan tersedia untuk komponen Anda hanya jika Anda menambahkan nama prop prop-nameke propsatribut Anda .


Saat data diteruskan dari komponen ke komponen lain karena beberapa peristiwa dinamis atau statis. Itu dilakukan dengan menggunakan operator acara dan penyiar. Jadi misalnya jika Anda memiliki struktur komponen seperti ini:

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

Dan Anda ingin mengirim data dari <my-child-A>ke <my-child-B>maka dalam <my-child-A>Anda harus mengirimkan sebuah acara:

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

Acara ini akan terus berlanjut hingga ke rantai induk. Dan dari orang tua mana pun Anda memiliki cabang ke arah <my-child-B>Anda menyiarkan acara bersama dengan datanya. Jadi pada orang tua:

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

Sekarang siaran ini akan merambah rantai anak. Dan di mana anak Anda ingin mengambil acara tersebut, dalam kasus <my-child-B>kami, kami akan menambahkan acara lain:

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

Cara ketiga untuk melewatkan data adalah melalui parameter di v-link. Metode ini digunakan ketika rantai komponen benar-benar hancur atau dalam kasus ketika URI berubah. Dan saya dapat melihat Anda sudah memahaminya.


Tentukan jenis komunikasi data yang Anda inginkan, dan pilih dengan tepat.

notANerdDev
sumber
1
Terima kasih, itu sangat membantu. Satu-satunya bagian yang masih saya perjuangkan adalah konvensi penamaan. yaitu: Saya memiliki nama pengguna yang saya kirimkan melalui v-link sebagai nama. Sekarang saya dapat mengedit variabel nama dan meneruskannya kembali ke komponen asli sebagai nama, tetapi komponen asli tidak memiliki var yang disebut name. Apa yang kulewatkan di sini? Tampaknya tidak mungkin melewatkan objek melalui v-link?
mundur
1
Anda sudah melewati suatu objek. paramsadalah sebuah objek. Kunci nama dapat ditetapkan ke this.user.namedalam komponen Anda. Buat biola jika Anda butuh bantuan, dan beri tahu saya. Lihat ini: vuejs.github.io/vue-router/en/route.html
notANerdDev
Ah, oke, saya mengerti sekarang. Terima kasih lagi. Saya menghargai bantuan Anda, itu benar-benar membuat segalanya menjadi lebih jelas.
mundur
6
Jawaban yang mengagumkan, tetapi seperti yang saya mengerti, ini tidak akan berfungsi dengan 2.0 karena acara sudah tidak digunakan lagi?
rix
2
Saya menyukai jawabannya tetapi kemudian mendapat komentar dan karena saya bekerja dengan Vue 2, saya merasa bahwa saya tidak akan dapat menggunakan metode kedua yang disarankan oleh Anda. Apakah itu benar-benar ditakuti?
Konrad Viltersten
23

Cara terbaik untuk mengirim data dari komponen induk ke anak menggunakan props .

Meneruskan data dari orang tua ke anak melalui props

  • Deklarasikan props(larik atau objek ) pada anak
  • Berikan kepada anak melalui <child :name="variableOnParent">

Lihat demo di bawah ini:

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.dll
sumber
perbaikan kecil: "<child-comp" alih-alih "<child" dan variableAtParent .. Berikan ke anak melalui <child-comp: name = "variableAtParent">
muenalan
Ini hanya akan bekerja dengan properti sederhana, referensi objek tidak akan diperbarui. Misalnya jika Anda memiliki properti induk be array, dan array ini diganti di objek induk ke array lain, anak tidak akan melihatnya.
Stan Sokolov
@StanSokolov tidak sama sekali. Saya bekerja untuk array, lihat: jsfiddle.net/acdcjunior/q4mank05 . Jika array Anda tidak reaktif, Anda mungkin menghadapi masalah reaktivitas. Coba gunakan Vue.set, selengkapnya di sini: vuejs.org/v2/guide/reactivity.html#For-Arrays
acdcjunior
Apa gunanya jika tidak reaktif? Yakin itu reaktif dengan referensi terus-menerus diganti dengan larik baru. Vue tidak menyebarkan "perubahan referensi" ke anak-anak, hanya menghargai perubahan pada elemen sederhana. Jadi jika referensi ke array ditimpa di induk, anak-anak masih akan melihat referensi lama. Tidak akan pernah tahu orang tua sekarang bekerja dengan objek yang berbeda.
Stan Sokolov
@StanSokolov Lihat ini: jsfiddle.net/acdcjunior/ftmrne2h array diganti di induk dan anak melihat / bereaksi terhadapnya (klik tombol untuk menguji). Atau apakah maksud Anda sesuatu yang lain? Jika demikian, akan sangat membantu jika Anda mengedit biola untuk menampilkannya
acdcjunior
15

Saya pikir masalahnya ada di sini:

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

Ketika Anda mengawali prop dengan :Anda menunjukkan ke Vue bahwa itu adalah variabel, bukan string. Jadi, Anda tidak membutuhkan {{}}sekitar user.name. Mencoba:

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

EDIT -----

Hal di atas benar, tetapi masalah yang lebih besar di sini adalah ketika Anda mengubah URL dan pergi ke rute baru, komponen asli menghilang. Agar komponen kedua dapat mengedit data induk, komponen kedua harus menjadi komponen turunan dari yang pertama, atau hanya sebagian dari komponen yang sama.

Jeff
sumber
Terima kasih jeff. Saya mencoba menghapus {{}} tetapi saya masih mendapatkan kesalahan yang sama.
mundur
2

Saya telah menemukan cara untuk meneruskan data induk ke ruang lingkup komponen di Vue, menurut saya ini sedikit hack tapi mungkin ini akan membantu Anda.

1) Data referensi di Vue Instance sebagai objek eksternal (data : dataObj)

2) Kemudian pada fungsi data return pada komponen anak tinggal return parentScope = dataObjdan voila. Sekarang Anda tidak dapat melakukan hal-hal seperti {{ parentScope.prop }}dan akan bekerja seperti pesona.

Semoga berhasil!

Lucas Serena
sumber
Itu menggabungkan kedua komponen bersama apa yang bisa baik-baik saja untuk pohon dan simpulnya, tetapi biasanya tidak disukai. Saya akan mencoba menghindari ini.
Desember
1

Respons yang disebutkan di atas berfungsi dengan baik, tetapi jika Anda ingin meneruskan data antara 2 komponen saudara, bus peristiwa juga dapat digunakan. Lihat blog ini yang akan membantu Anda lebih memahami.

misalkan untuk 2 komponen: CompA & CompB memiliki induk dan main.js yang sama untuk menyiapkan aplikasi vue utama. Untuk meneruskan data dari CompA ke CompB tanpa melibatkan komponen induk, Anda dapat melakukan hal berikut.

di file main.js, deklarasikan instance global Vue yang terpisah, yang akan menjadi event bus.

export const bus = new Vue();

Di CompA, tempat acara dibuat: Anda harus memancarkan acara ke bus.

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

Sekarang tugasnya adalah mendengarkan acara yang dipancarkan, jadi, di CompB, Anda bisa mendengarkan seperti.

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

Keuntungan:

  • Kurangi & bersihkan kode.
  • Orang tua tidak boleh terlibat dalam meneruskan data dari 1 comp anak ke yang lain (seiring bertambahnya jumlah anak, akan sulit untuk mempertahankannya)
  • Mengikuti pendekatan pub-sub.
Divesh Sahu
sumber
0

Saya mengakses properti utama menggunakan $root.

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

Variabel JS global (objek) dapat digunakan untuk melewatkan data antar komponen. Contoh: Meneruskan data dari Ammlogin.vue ke Options.vue. Dalam Ammlogin.vue rspData diatur ke respon dari server. Di Options.vue, respons dari server tersedia melalui 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>
Kjelle J.
sumber