Dapatkan data dari satu komponen Vue di komponen lain?

Saya menggunakan Vue.js 2.5.13 dan memiliki struktur ini:

komponen-satu.vue:

    <template>
      <div>
        <input type="text" v-model="input_one">
        <component-two></component-two>
      </div>
    </template>

    <script>
      import ComponentTwo from 'component-two.vue'

      export default {
        name: "component-one",
        components: {
          ComponentTwo
        },
        data() {
          return {
            input_one: 'Hello from ComponentOne',
            input_two: ... // <-- I want to get value from ComponentTwo input_two (v-model) here
          }
        }
      }
    </script>

komponen-dua.vue:

    <template>
      <div>
        <input type="text" v-model="input_two">
      </div>
    </template>

    <script>
      export default {
        name: "component-two",
        data() {
          return {
            input_one: 'Hello from ComponentTwo'
          }
        }
      }
    </script>

Bagaimana cara mendapatkan data dari ComponentTwo di komponen ComponentOne? Ini penting bagi saya, karena saya memiliki banyak komponen yang mirip dengan bidang (formulir situs pendaftaran yang besar) dan tidak tahu tentang pemanggilan data antar komponen Vue..


person koddr    schedule 29.01.2018    source sumber
comment
Kemungkinan duplikat Berbagi data di berbagai komponen di Vuejs   -  person Roy J    schedule 29.01.2018
comment
@RoyJ - Saya rasa saya tidak akan mereferensikannya sebagai kemungkinan duplikat karena jawaban tersebut mengusulkan penggunaan pengubah .sync yang memiliki telah dihapus dari vue. Namun, yang pasti, ada banyak pertanyaan lain yang dijawab oleh penyedia untuk situasi ini.   -  person PatrickSteele    schedule 29.01.2018


Jawaban (5)


Anda dapat dengan mudah mencapainya menggunakan bus acara global.

https://alligator.io/vuejs/global-event-bus/

Untuk aplikasi yang lebih besar dan kompleks, saya sarankan menggunakan alat manajemen status seperti vuex.

https://vuex.vuejs.org/en/

person Community    schedule 29.01.2018

Vuejs menggunakan "props" untuk komunikasi orang tua/anak dan "memancarkan" peristiwa untuk komunikasi anak/orang tua

masukkan deskripsi gambar di sini

Anda harus ingat bahwa untuk setiap props yang Anda teruskan ke komponen anak, Anda harus memasukkan props tersebut ke array props. Hal yang sama berlaku untuk acara, setiap acara yang Anda pancarkan harus Anda tangkap di komponen induk, jadi:

komponen-satu.vue:

    <template>
      <div>
        <input type="text" v-model="input_one">
        <component-two
            @CustomEventInputChanged="doSomenthing">
        </component-two>
      </div>
    </template>

    <script>
      import ComponentTwo from 'component-two.vue'

      export default {
        name: "component-one",
        components: {
          ComponentTwo
        },
        data() {
          return {
            input_one: 'Hello from ComponentOne',
            input_two: ''
          }
        },
        methods: {
            doSomenthing ( data ) {
                this.input_two = data;
            }
        }
      }
    </script>

komponen-dua.vue:

    <template>
      <div>
        <input type="text" v-model="input_two" @change="emitEventChanged>
      </div>
    </template>

    <script>
      export default {
        name: "component-two",
        data() {
          return {
            input_one: 'Hello from ComponentTwo'
          }
        },
        methods: {
            emitEventChanged () {
                this.$emit('CustomEventInputChanged', this.input_two);
            }
        }

      }
    </script>

Ini seharusnya berhasil

person Luca Giardina    schedule 29.01.2018

Anda perlu mengimplementasikan sistem yang mengirim v-model kembali ke induknya.

Hal ini dapat dilakukan dengan menggunakan properti terhitung di dalam component-two yang memunculkan perubahan di dalam metode setnya.

Contoh:

Vue.component('component-two', {
  name: 'component-two',
  template: '#component-two-template',
  props: {
    value: {
      required: true,
      type: String,
    },
  },
  computed: {
    message: {
      get() {
        return this.value;
      },
      set(val) {
        this.$emit('input', val);
      },
    },
  },
});

var app = new Vue({
  el: '#app',
  data: {
    message1: 'm1',
    message2: 'm2',
  },
});
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script type="text/x-template" id="component-two-template">
  <input type="text" v-model="message"/>
</script>
<div id="app">
  <input type="text" v-model="message1"/>
  <component-two v-model="message2"></component-two>
  <p>Output</p>
  <pre>{{message1}}</pre>
  <pre>{{message2}}</pre>
</div>

person Ferrybig    schedule 29.01.2018

Ada beberapa cara untuk melakukannya, dan beberapa diantaranya disebutkan dalam jawaban lain:
(tanpa urutan tertentu, Baca bagian detail di bawah untuk info lebih lanjut)

  1. Gunakan eventbus global
  2. Gunakan props pada komponen
  3. Gunakan atribut v-model
  4. Gunakan pengubah sinkronisasi
  5. Gunakan Vuex

Untuk pengikatan dua arah perlu diingat dapat menyebabkan rantai mutasi yang sulit dipertahankan, dikutip dari dokumen:

Sayangnya, pengikatan dua arah yang sebenarnya dapat menimbulkan masalah pemeliharaan, karena komponen turunan dapat memutasi komponen induk tanpa sumber mutasi tersebut terlihat jelas pada komponen induk dan turunannya.

Berikut adalah beberapa rincian metode yang tersedia:

1.) Gunakan bus peristiwa global

Saya sangat menyarankan untuk tidak menggunakan pendekatan ini untuk segala jenis komunikasi umum antar komponen, seperti yang telah dibahas di banyak tempat seperti di sini

2.) Gunakan props pada komponen

Alat peraga mudah digunakan dan merupakan cara ideal untuk memecahkan sebagian besar masalah umum.
Karena cara Vue mengamati perubahan semua properti harus tersedia pada suatu objek atau properti tersebut tidak akan reaktif. Jika ada properti yang ditambahkan setelah Vue selesai membuatnya dapat diamati, 'set' harus ditambahkan digunakan.

 //Normal usage
 Vue.set(aVariable, 'aNewProp', 42);
 //This is how to use it in Nuxt
 this.$set(this.historyEntry, 'date', new Date());

Objek akan reaktif untuk komponen dan induknya:

Jika Anda meneruskan objek/array sebagai penyangga, itu akan menyinkronkan dua arah secara otomatis - mengubah data di anak, itu diubah di induk.

Jika Anda meneruskan nilai sederhana (string, angka) melalui props, Anda harus secara eksplisit menggunakan pengubah sinkronisasi

Seperti dikutip dari --> https://stackoverflow.com/a/35723888/1087372

3.) Gunakan atribut v-model

Atribut v-model adalah gula sintaksis yang memungkinkan pengikatan dua arah yang mudah antara induk dan anak. Ia melakukan hal yang sama seperti pengubah sinkronisasi, hanya saja ia menggunakan prop tertentu dan peristiwa tertentu untuk pengikatan

Ini:

 <input v-model="searchText">

sama dengan ini:

 <input
   v-bind:value="searchText"
   v-on:input="searchText = $event.target.value"
 >

Dimana prop harus berupa nilai dan kejadian harus berupa input

4.) Gunakan pengubah sinkronisasi

Pengubah sinkronisasi juga merupakan gula sintaksis dan melakukan hal yang sama seperti v-model, hanya saja nama prop dan acaranya ditentukan oleh apa pun yang sedang digunakan.

Di induknya dapat digunakan sebagai berikut:

 <text-document v-bind:title.sync="doc.title"></text-document>

Dari anak, sebuah peristiwa dapat dikeluarkan untuk memberi tahu orang tua tentang perubahan apa pun:

 this.$emit('update:title', newTitle)

5.) Gunakan Vuex

Vuex adalah penyimpanan data yang dapat diakses dari setiap komponen. Perubahan dapat berlangganan.

Dengan menggunakan Vuex store lebih mudah untuk melihat aliran mutasi data dan didefinisikan secara eksplisit. Dengan menggunakan alat pengembang vue, Anda dapat dengan mudah melakukan debug dan mengembalikan perubahan yang telah dibuat.

Pendekatan ini memerlukan lebih banyak contoh, namun jika digunakan di seluruh proyek, pendekatan ini menjadi cara yang lebih mudah untuk menentukan bagaimana perubahan dilakukan dan dari mana.

Lihat panduan memulai

person SanBen    schedule 30.04.2020

Anda dapat menggunakan .sync Pengubah

<template>
  <div>
    <input type="text" v-model="input_one">
    <component-two :secondValue.sync="input_two"></component-two>
  </div>
</template>

<script>
  import ComponentTwo from 'component-two.vue'

  export default {
    name: "component-one",
    components: {
      ComponentTwo
    },
    data() {
      return {
        input_one: 'Hello from ComponentOne',
        input_two: ''
      }
    }
  }
</script>

komponen-dua.vue:

<template>
  <div>
    <input type="text" v-model="input_two">
  </div>
</template>

<script>
  export default {
    name: "component-two",
    data() {
      return {
        input_one: 'Hello from ComponentTwo',
        input_two: ''
      },
      watch: {
        input_two : function(val){
          this.$emit('update:secondValue', val)
        }
      }
    }
  }
</script>
person El Danielo    schedule 29.01.2018