vuejs alt bileşenden üst verileri günceller


166

Vuejs (2.0) ile oynamaya başlıyorum. İçinde tek bileşen bulunan basit bir sayfa oluşturdum. Sayfada veriler içeren bir Vue örneği vardır. Bu sayfada, bileşeni html'ye kaydettim ve ekledim. Bileşende bir tane var input[type=text]. Bu değerin üst öğeye (ana Vue örneği) yansımasını istiyorum.

Bileşenin üst verilerini nasıl doğru şekilde güncellerim? Üst öğeden bağlı bir prop iletmek iyi değildir ve konsola bazı uyarılar gönderir. Belgelerinde bir şey var ama işe yaramıyor.


1
Çalışmayan denediğiniz kodu ekleyebilir misiniz?
Saurabh


Bu iletişim şu şekilde kurulabilir: emit olayı veya vuex.
Nguyenn Trọng Thành

Yanıtlar:


194

İki yönlü bağlama, daha olay odaklı bir mimarinin kullanılması lehine Vue 2.0'da kullanımdan kaldırılmıştır. Genel olarak, bir çocuk sahne donanımını değiştirmemelidir. Aksine, $emitolayları yapmalı ve ebeveynin bu olaylara yanıt vermesine izin vermelidir .

Özel durumunuzda, özel bir bileşen kullanabilirsiniz v-model. Bu, iki yönlü bağlamaya yakın bir şeye izin veren özel bir sözdizimidir, ancak aslında yukarıda açıklanan olay odaklı mimari için bir kısaltmadır. Burada okuyabilirsiniz -> https://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events .

İşte basit bir örnek:

Vue.component('child', {
  template: '#child',
  
  //The child has a prop named 'value'. v-model will automatically bind to this prop
  props: ['value'],
  methods: {
    updateValue: function (value) {
      this.$emit('input', value);
    }
  }
});

new Vue({
  el: '#app',
  data: {
    parentValue: 'hello'
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{parentValue}}</p>
  <child v-model="parentValue"></child>
</div>

<template id="child">
   <input type="text" v-bind:value="value" v-on:input="updateValue($event.target.value)">
</template>


Dokümanlar şunu belirtir:

<custom-input v-bind:value="something" v-on:input="something = arguments[0]"></custom-input>

eşdeğerdir

<custom-input v-model="something"></custom-input>

Bu nedenle, çocuk üzerindeki pervanenin değer olarak adlandırılması gerekir ve bu nedenle çocuğun, adlandırılmış bir olayı $ yayması gerekir input.


ilk yanıt için teşekkürler. Lütfen genişletin veya 'girdi' etkinliğiyle ilgili belgelere işaret edin. yerleşik bir olay gibi görünüyor.
Gal Ziv

Bir açıklama ekledim ve dokümantasyon bağlantısını daha açık hale getirdim.
asemahle

1
Bileşen ve oluşturulan işlev için prop "değerini" atladım ve hala çalışıyor. neden kullandığını açıklayabilir misin?
xetra11

1
Pervaneyi eklemezseniz undefined, ilk değişikliğe kadar olacaktır . Yorum yaptığım bu kemanı görün props: ['value']. Başlangıç değeri ne olduğuna dikkat edin undefinedyerine, hello: jsfiddle.net/asemahle/8Lrkfxj6 . İlk değişiklikten sonra Vue, bileşene dinamik olarak bir değer propu ekler, böylece çalışır.
asemahle

Dokümanlarda bunun hemen arkasını okudum. Harika bir çalışma örneği. Yapabilseydim +10!
kil

126

Gönderen belgeler :

Vue.js'de, üst-alt bileşen ilişkisi props aşağı, olaylar yukarı olarak özetlenebilir. Ebeveyn, props aracılığıyla verileri çocuğa aktarır ve çocuk, olaylar aracılığıyla ebeveyne mesajlar gönderir. Şimdi nasıl çalıştıklarını görelim.

görüntü açıklamasını buraya girin

Sahne nasıl geçilir

Alt öğeye props iletmek için kod aşağıdadır:

<div>
  <input v-model="parentMsg">
  <br>
  <child v-bind:my-message="parentMsg"></child>
</div>

Olay nasıl yayılır

HTML:

<div id="counter-event-example">
  <p>{{ total }}</p>
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>

JS:

Vue.component('button-counter', {
  template: '<button v-on:click="increment">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    increment: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})
new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})

5
ya "artış" işlevi üst bileşendeyse ve ben onu alt bileşenden tetiklemek istersem?
Hamzaouiii

kavramı kavrama anı, her ne kadar hacky kopyala yapıştır ile defalarca kullanılıyor olsa da ...
Yordan Georgiev

1
O grafiği yazdırıp kafama yapıştıracağım. Teşekkürler!
domih

1
Bu örnekte, kök bileşende tanımlanmış bir olay dinleyicimiz olması gerekmez mi? Şuna benzer bir şey: `` mount () {this.on ('increment', () => {this.incrementTotal ();}); } ``
jmk2142

110

Alt bileşende:

this.$emit('eventname', this.variable)

Üst bileşende:

<component @eventname="updateparent"></component>

methods: {
    updateparent(variable) {
        this.parentvariable = variable
    }
}

4
Bu örnek aklımı uçurdu. Buraya gelmeden önce kaç tane öğreticiden
geçtiğime

@Sarvar Nishonboev - güncelleştirme yöntemi ebeveyn değişkeni güncellediğinde, onu "otomatik olarak" alt öğeye destek olarak geri gönderir mi?
veritas

1
@veritas - hayır, bu durumda değil çünkü alt bileşen bir destek olarak parentvariable almıyor. Olsaydı, olurdu.
jomofrodo

21

Alt Bileşen

this.$emit('event_name')Üst bileşene bir olay göndermek için kullanın .

görüntü açıklamasını buraya girin

Ana Bileşen

Üst bileşendeki bu olayı dinlemek için yaparız v-on:event_nameve ex. handleChangebu olayda yürütmek istediğimiz bir yöntem ( ) gerçekleşir

görüntü açıklamasını buraya girin

Bitti :)


15

Yukarıdakiler için yayan olay ve v-model cevaplarına katılıyorum. Ancak, bu, google tarafından döndürülen ilk makalelerden biri gibi göründüğü için, çoklu form öğelerine sahip bileşenler hakkında bulduğum şeyleri ana babalarına geri göndermek isteyenleri göndereceğimi düşündüm.

Sorunun tek bir girişi belirttiğini biliyorum, ancak bu en yakın eşleşme gibi görünüyordu ve insanlara benzer vue bileşenleri ile biraz zaman kazandırabilir. Ayrıca, henüz hiç kimse .syncdeğiştiriciden bahsetmedi .

Bildiğim kadarıyla, v-modelçözüm yalnızca ebeveynlerine dönen bir girdiye uygundur. Onu aramak için biraz zaman aldım, ancak Vue (2.3.0) dokümantasyonu, bileşene gönderilen birden fazla nesnenin ana öğeye nasıl senkronize edileceğini gösteriyor (elbette emit aracılığıyla).

Uygun şekilde .syncdeğiştirici olarak adlandırılır .

İşte budur dokümantasyon diyor ki:

Bazı durumlarda, bir destek için "iki yönlü bağlama" ihtiyacımız olabilir. Ne yazık ki, gerçek iki yönlü bağlama bakım sorunları yaratabilir, çünkü alt bileşenler, bu mutasyonun kaynağı hem ebeveynde hem de çocukta açık olmadan ebeveyni mutasyona uğratabilir.

Bu nedenle, bunun yerine, düzenindeki olayları yayınlamanızı öneririz update:myPropName. Örneğin, bir titledestek içeren varsayımsal bir bileşende, yeni bir değer atama niyetini şu şekilde iletebiliriz:

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

Daha sonra ebeveyn, isterse bu olayı dinleyebilir ve yerel bir veri özelliğini güncelleyebilir. Örneğin:

<text-document   
 v-bind:title="doc.title"  
 v-on:update:title="doc.title = $event"
></text-document>

Kolaylık sağlamak için, .sync değiştiricisiyle bu kalıp için bir kısaltma sunuyoruz:

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

Ayrıca, bir nesne üzerinden göndererek bir seferde birden çok öğeyi senkronize edebilirsiniz. Belgelere buradan göz atın


Aradığım buydu. Çok teşekkürler.
Thomas

Bu, 2020 itibariyle en iyi ve en güncel çözümdür. Çok teşekkürler!
Marcelo

8

Daha basit yol kullanmaktır this.$emit

Father.vue

<template>
  <div>
    <h1>{{ message }}</h1>
    <child v-on:listenerChild="listenerChild"/>
  </div>
</template>

<script>
import Child from "./Child";
export default {
  name: "Father",
  data() {
    return {
      message: "Where are you, my Child?"
    };
  },
  components: {
    Child
  },
  methods: {
    listenerChild(reply) {
      this.message = reply;
    }
  }
};
</script>

Child.vue

<template>
  <div>
    <button @click="replyDaddy">Reply Daddy</button>
  </div>
</template>

<script>
export default {
  name: "Child",
  methods: {
    replyDaddy() {
      this.$emit("listenerChild", "I'm here my Daddy!");
    }
  }
};
</script>

Tam örneğim: https://codesandbox.io/s/update-parent-property-ufj4b


5

Nesne veya Dizi olarak da sahne almak mümkündür. Bu durumda veriler iki yönlü olarak bağlanacaktır:

(Bu, konunun sonunda belirtilmiştir: https://vuejs.org/v2/guide/components.html#One-Way verileri-Flow )

Vue.component('child', {
  template: '#child',
  props: {post: Object},
  methods: {
    updateValue: function () {
      this.$emit('changed');
    }
  }
});

new Vue({
  el: '#app',
  data: {
    post: {msg: 'hello'},
    changed: false
  },
  methods: {
    saveChanges() {
        this.changed = true;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{post.msg}}</p>
  <p v-if="changed == true">Parent msg: Data been changed - received signal from child!</p>
  <child :post="post" v-on:changed="saveChanges"></child>
</div>

<template id="child">
   <input type="text" v-model="post.msg" v-on:input="updateValue()">
</template>



0

1) Alt Bileşen: Alt bileşen yazımında şöyle kullanabilirsiniz: this.formValue, bazı verileri üst bileşene göndermek içindir

this.$emit('send',this.formValue)

2) Parrent Compnenet: ve parrent bileşen etiketinde şunun gibi gönderme değişkenini al: ve bu, ana bileşen etiketindeki alt bileşen verilerini almak için koddur

@send="newformValue"

0

Başka bir yol da, ayarlayıcınızın bir referansını bir pervane olarak ebeveynden alt bileşene, React'te yaptıklarına benzer şekilde iletmektir. Söylesene, bir yöntem var updateValuebunu gibi çocuk bileşeni örneğini verebilir, değerini güncellemek için ebeveyn tarih: <child :updateValue="updateValue"></child>. Sonra çocuğa bir karşılık gelen pervane sahip olacaktır: props: {updateValue: Function}ve giriş değiştiğinde şablonda yöntemini çağırın: <input @input="updateValue($event.target.value)">.


0

Nedenini bilmiyorum, ancak verileri nesne olarak kullanarak ana verileri başarıyla güncelledim, :set vecomputed

Parent.vue

<!-- check inventory status - component -->
    <CheckInventory :inventory="inventory"></CheckInventory>

data() {
            return {
                inventory: {
                    status: null
                },
            }
        },

Child.vue

<div :set="checkInventory">

props: ['inventory'],

computed: {
            checkInventory() {

                this.inventory.status = "Out of stock";
                return this.inventory.status;

            },
        }

0

onun örneği, gönder düğmesindeki giriş değerini ebeveyne nasıl ileteceğinizi anlatacaktır.

Önce eventBus'u yeni Vue olarak tanımlayın.

//main.js
import Vue from 'vue';
export const eventBus = new Vue();

Pass your input value via Emit.
//Sender Page
import { eventBus } from "../main";
methods: {
//passing data via eventbus
    resetSegmentbtn: function(InputValue) {
        eventBus.$emit("resetAllSegment", InputValue);
    }
}

//Receiver Page
import { eventBus } from "../main";

created() {
     eventBus.$on("resetAllSegment", data => {
         console.log(data);//fetching data
    });
}


0

Çocukta

 <input
            type="number"
            class="form-control"
            id="phoneNumber"
            placeholder
            v-model="contact_number"
            v-on:input="(event) => this.$emit('phoneNumber', event.target.value)"
    />

data(){
    return {
      contact_number : this.contact_number_props
    }
  },
  props : ['contact_number_props']

Ebeveyn olarak

<contact-component v-on:phoneNumber="eventPhoneNumber" :contact_number_props="contact_number"></contact-component>


 methods : {
     eventPhoneNumber (value) {
      this.contact_number = value
    }

0

Üst Düzeyde ->

data : function(){
            return {
                siteEntered : false, 
            };
        },

Alt Bileşende ->

this.$parent.$data.siteEntered = true;

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.