vuejsは子コンポーネントから親データを更新します


154

私はvuejs(2.0)で遊んでいます。1つのコンポーネントを含む単純なページを作成しました。ページには、データを含む1つのVueインスタンスがあります。そのページで、コンポーネントを登録してhtmlに追加しました。コンポーネントには1つありinput[type=text]ます。その値を親(メインVueインスタンス)に反映させたい。

コンポーネントの親データを正しく更新するにはどうすればよいですか?バインドされた小道具を親から渡すのはよくなく、コンソールにいくつかの警告をスローします。彼らは彼らのドキュメントに何かを持っていますが、それは機能していません。


1
機能していない、試したコードを追加できますか?
Saurabh

回答:


181

双方向バインディングは、よりイベント駆動型のアーキテクチャを使用するために、Vue 2.0で廃止されました。一般的に、子供は小道具を変異させてはなりません。むしろ、それは$emitイベントであり、親にそれらのイベントに応答させるべきです。

特定のケースでは、でカスタムコンポーネントを使用できますv-model。これは、双方向バインディングに近いものを可能にする特別な構文ですが、実際には上記のイベント駆動型アーキテクチャの省略形です。あなたはそれについてここで読むことができます-> https://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events

以下に簡単な例を示します。

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>


ドキュメントには、

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

に相当

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

これが、子の小道具に値という名前を付ける必要があり、子がという名前のイベントを$ emitする必要がある理由inputです。


最初の応答に感謝します。拡大していただけますか、それとも「入力」イベントに関するドキュメントをよりよく示していただけますか 組み込みイベントのようです。
Gal Ziv

説明を追加し、ドキュメントへのリンクをより明確にしました。
asemahle

1
コンポーネントと作成した関数のプロップ「値」を省略しても、引き続き機能します。なぜそれを使用したのか説明できますか?
xetra11 2017年

1
プロップを追加しない場合undefined、最初の変更までになります。私がコメントアウトしたこのフィドルを参照してくださいprops: ['value']。初期値がどのように注意してくださいundefined、代わりにhellojsfiddle.net/asemahle/8Lrkfxj6。最初の変更後、Vueはコンポーネントに値プロップを動的に追加するため、機能します。
asemahle 2017年

私はこれをすぐにドキュメントで読みました。素晴らしい実例。できれば+10!
クレイ

121

ドキュメントから:

Vue.jsでは、親子コンポーネントの関係は、小道具のダウン、イベントのアップとして要約できます。親はプロップを介して子にデータを渡し、子はイベントを介して親にメッセージを送信します。次に、それらがどのように機能するかを見てみましょう。

ここに画像の説明を入力してください

小道具を渡す方法

以下は、小道具を子要素に渡すコードです。

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

イベントを発行する方法

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
関数「increment」が親コンポーネントにあり、子コンポーネントからトリガーしたい場合はどうなりますか?
Hamzaouiii 2018

コンセプトを把握する剪断モーメント、ただしハッキングコピーペーストによって何度か使用されてきた...
Yordan Georgiev

1
そのグラフィックを印刷して頭に貼ります。どうも!
ドミ

1
この例では、ルートコンポーネントでイベントリスナーを定義してはいけませんか?次のようなもの: `` `Mounted(){this.on( 'increment'、()=> {this.incrementTotal();}); } `` `
jmk2142

94

子コンポーネント:

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

親コンポーネント:

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

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

3
私の心は単にこの例に吹き飛ばされています。私がここに来る前に、いくつのチュートリアルを行ったかわかりません...
suchislife

18

子コンポーネント

this.$emit('event_name')イベントを親コンポーネントに送信するために使用します。

ここに画像の説明を入力してください

親コンポーネント

親コンポーネントでそのイベントをリッスンするために、そのイベントで実行するv-on:event_nameメソッド(ex. handleChange)を実行します

ここに画像の説明を入力してください

完了:)


13

上記のイベント発行とvモデルの回答に同意します。ただし、これはgoogleによって返される最初の記事の1つであると思われるため、親に返送したい複数のフォーム要素を持つコンポーネントについて見つけたものを投稿すると思いました。

私は質問が単一の入力を指定していることを知っていますが、これは最も近い一致のようであり、同様のVueコンポーネントを使用して人々を時間を節約する可能性があります。また、誰も.syncまだ修飾子について言及していません。

私の知る限り、v-modelソリューションは親に戻る1つの入力にのみ適しています。少し時間をかけて探しましたが、Vue(2.3.0)のドキュメントには、コンポーネントに送信された複数のプロップを親に同期する方法が示されています(もちろん、emitによって)。

適切に.sync修飾子と呼ばれます。

ここでは何であるドキュメントは言います:

場合によっては、小道具に「双方向バインディング」が必要になることがあります。残念ながら、真の双方向バインディングはメンテナンスの問題を引き起こす可能性があります。これは、子コンポーネントが、親と子の両方で変更のソースが明らかでない場合でも、親を変更できるためです。

そのため、代わりにのパターンでイベントを発行することをお勧めします update:myPropName。たとえば、title小道具を持つ架空のコンポーネントでは 、新しい値を割り当てる意図を次のように伝えることができます。

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

その後、必要に応じて、親はそのイベントをリッスンしてローカルデータプロパティを更新できます。例えば:

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

便宜上、.sync修飾子を使用してこのパターンの省略表現を提供します。

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

オブジェクトを介して送信することにより、一度に複数を同期することもできます。こちらドキュメントをご覧ください


これは私が探していたものです。どうもありがとう。
トーマス

これは、2020年の時点で最高かつ最新のソリューションです。どうもありがとうございました。
Marcelo

6

より簡単な方法は使用です 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>

私の完全な例:https : //codesandbox.io/s/update-parent-property-ufj4b


5

小道具をオブジェクトまたは配列として渡すことも可能です。この場合、データは双方向にバインドされます。

(これはトピックの最後に記載されています:https : //vuejs.org/v2/guide/components.html#One-Way-Data-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)子コンポーネント:子コンポーネントでこのように使用できます。次のように記述します。this.formValueは親コンポーネントにデータを送信します

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

2)Parrent Compnenet:そして、parrentコンポーネントタグでは、このような送信変数を受け取ります:これは、親コンポーネントタグでその子コンポーネントデータを受け取るコードです

@send="newformValue"

0

別の方法は、セッターの参照を親から小道具として子コンポーネントに渡すことです。これは、Reactで行う方法と同様です。たとえば、updateValue親に値を更新するメソッドがあり、次のように子コンポーネントをインスタンス化できるとします<child :updateValue="updateValue"></child>。次に、子に対応するプロップprops: {updateValue: Function}があります<input @input="updateValue($event.target.value)">。テンプレートでは、入力が変化したときにメソッドを呼び出します。


0

理由はわかりませんが、データをオブジェクトとして使用して親データを正常に更新しました:setcomputed

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

この例では、送信ボタンで入力値を親に渡す方法を説明しています。

最初にeventBusを新しいVueとして定義します。

//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

これでうまくいくと思います:

@change="$emit(variable)"

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.