82
65

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vue.jsでコンポーネントの親子間でデータのやり取りを行う方法

Last updated at Posted at 2019-01-02

最近Vue.jsを使ったプロジェクトに手を出しています。
そこでコンポーネント間で値をやり取りする方法を調べていましたが、
こうするべきでしょ、というのを私なりに探っていった結果をまとめました。

こちらのコードの例で使用しているVueのバージョンは2.5.21です。

親から子に単方向でやり取りする方法

親コンポーネントから子コンポーネントに一方的にデータの値を渡して、
子からはそれを変更しても、親に変更は伝搬させない場合のやり方です。

シンプルにpropsに渡す

propsで親のもつ値を渡します。Vueを使うなら普通のやり方ですね。

See the Pen vue component test parent -&rt; child by stoba (@rhistoba) on CodePen.

子から親に単方向でやり取りする方法

子コンポーネントのもつデータの変更を、親コンポーネントに一方的に伝搬させる方法です。

$emitを使う

子コンポーネントでthis.$emitを実行すると、値の変更があったことをイベントとして値とともに親に知らせることができます。
親はそのイベントがトリガされた場合の処理をmethodsに書きます。

See the Pen vue component test parent <- child by stoba (@rhistoba) on CodePen.

(好ましくない例)$parentで親のプロパティを参照する

子コンポーネントでthis.$parentを使って親コンポーネントのデータを参照して、そこに直接値を代入する方法です。
しかし、これは親がデータとして何を持つべきかを子が縛ることになるので、使わない方がいいでしょう。

See the Pen vue component test parent <- child bad case by stoba (@rhistoba) on CodePen.

親子で双方向にやり取りする方法

親子両方からの変更に対して、双方ともにデータの変更を伝搬させる方法です。

(不可能な例)子のpropsの値を直接変更する

子のpropsにある、親から渡されたデータを直接変更すればよさそうに思えますが、不可能です。
propsの子からの変更は親に対して変更を与えません。
参考: https://jp.vuejs.org/v2/guide/components-props.html#%E5%8D%98%E6%96%B9%E5%90%91%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%83%95%E3%83%AD%E3%83%BC

See the Pen vue component test parent <-&rt; child bad case 1 by stoba (@rhistoba) on CodePen.

(好ましくない例)$parentを使う

前述の$parentを使って親のデータを直接参照する方法です。
実現こそ可能でコード量こそ少なくて済みますが、前述通り親のデータを子が縛ることになるので、
使わない方がいいでしょう。

See the Pen vue component test parent <-&rt; child bad case $parent by stoba (@rhistoba) on CodePen.

propsで親のデータを受け取り、$emitで変更をトリガする

前述の単方向のやり方を組み合わせた方法です。
冗長な感じに思えますが、親子間の双方向のやり取りはこれが基本となると思います。

See the Pen vue component test parent <-&rt; child by stoba (@rhistoba) on CodePen.

v-modelを使う

v-modelディレクティブを使うことで、上の冗長な感じをある程度改善することができます。
親側で子コンポーネントを使用する際、v-model="message"と記述することで、
:value="message" @input="message = $event"と同義になります。
そのため、子コンポーネントでプロパティにvalueを指定して、$emit('input')でイベントを送出することで、
親側で子のプロパティ変更のイベントに対する処理を記述する必要が無くなり、コンポーネントが再利用しやすくなります。
参考: https://jp.vuejs.org/v2/guide/components.html#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%A7-v-model-%E3%82%92%E4%BD%BF%E3%81%86

ただし、子コンポーネントのプロパティで使う名前が強制的にvalueになってしまうため、
これにエイリアスを与えてどのような値であるかを明示的にしたいですね。
そのため、computedで単純にvalueを返すgetterメソッドを用意するようにしましょう。

双方向のやり取りは、このやり方が最も実用的ではないでしょうか。

See the Pen vue component test parent <-&rt; child v-model bad case by stoba (@rhistoba) on CodePen.

まとめ

以上、Vueで親子コンポーネントでデータの値をやり取りする方法でした。
重要なのは、変更の処理($emit)と参照(computedなど)を切り分けて明確に行うことだと考えます。
これはReduxVuexといったfluxアーキテクチャでも同様な考えが含まれますが、
Vue単体でもそれを考慮したプログラミングが必要だと思います。

82
65
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
82
65

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?