Linuxなどのメモ書き

Vue.js propsとdataの違い


1. 概要

Vue.jsでpropsとdataの違いは何?とたまに聞かれるので、そのメモとサンプル。インスタンス内からはどちらもthis.xxxでアクセスできるため、余計に区別がつかなくなるのだと思う。

 

2. プロパティはどのように使うか

まず前提として、プロパティ(props)はVueインスタンスではなく、コンポーネント(Vue.component)内で使うもの。

その上で、プロパティは親からコンポーネントにパラメータを渡すのに使用する。具体的にはプロパティを使うのは以下のケースがある。

(1) タグの属性でパラメータを渡したい場合

コンポーネントタグの属性でパラメータを渡したい場合はプロパティ(props)を使う必要がある。dataでは渡せない。

サンプル1: https://www.bit-hive.com/~tomita/data_vs_props2/example.html

(サンプルは単体のhtmlにまとまっているので、ソースを表示すれば内容は簡単に確認できます)

サンプルのコンポーネントMyComponentには以下のようにtitle_in_propsプロパティとtitle_in_dataデータが定義されている。

    props: ['title_in_props'],
    data: function () {
      return {title_in_data: '--'};
    }

このコンポーネントに以下のように属性でtitle_in_propsとtitle_in_dataを指定してみる。

<my-component title_in_props="foo" title_in_data="bar"></my-component>

表示結果は以下となり、プロパティのtitle_in_propsのみ設定できていることが確認できる。

Title In Props: foo, Title In Data: --

 

(2) 親から子コンポーネントへパラメータを渡したい場合

(1)では属性で静的な値を指定していたが、動的な値を指定したい場合はこちらの方法をとる。
v-bind:<プロパティ名>でコンポーネントのプロパティと親のデータをバインディングすることで、親のデータを変更した際、子のプロパティも更新されるようにする。

サンプル2: https://www.bit-hive.com/~tomita/data_vs_props2/example2.html

このサンプルでは以下のtitleプロパティを持つNewsComponentとtitleの大元のデータを持つVueインスタンスが存在する。

  Vue.component('NewsComponent', {
    template: '<p>Title: {{ title }}</p>',
    props: ['title']
  });

  var vm = new Vue({
    el: '#app',
    data: {
      news: {title: 'Hello'}
    }
  });

表示しているNewsComponentには以下のようにv-bindでVueインスタンスのnews.titleのデータをバインディングしている。

<news-component v-bind:title="news.title" ref="component1"></news-component>

「Add ! to parent data.」ボタンを押すとVueインスタンスのnews.titleの末尾にエクスクラメーションマーク(!)を追加する。news.titleを更新すると、バインディングしたNewsComponentのtitleプロパティも更新され、表示も更新される。

このように親のデータが変更されたらコンポーネント内のデータを更新したい場合にプロパティを使用する。

「Add ? to title property directly.」ボタンの方はここでは説明しない。「3. プロパティの単方向データフロー」で説明する。

 

(1),(2)と分けて説明したが、どちらもコンポーネントタグの属性でパラメータを渡したい場合はプロパティを使うという点では同じである。プロパティの値が静的か親の更新によって変更されるか(動的)かの違いしかない。

上記以外ケースではpropsではなくdataを使えばよい。

 

3. プロパティの単方向データフロー

上記(2)に関連するが、親のプロパティを更新すると子のプロパティも更新されるが、逆はない。必ず親→子への単方向の伝搬となる。

このため、子のプロパティを直接変更することはしてはいけない。変更するとコンソールに警告が出力される(図1)。また、子のプロパティを変更しても、親のデータ更新時に再伝搬され上書きされてしまうので意味がない。

これはサンプル2の「Add ? to title property directly.」ボタンを押した後、「Add ! to parent data.」ボタンを押すことで確認できる。「Add ? to title property directly.」はコンポーネントのプロパティを直接変更するので、親のVueインスタンスのnews.titleは変更されない。「Add ! to parent data.」を押した場合、新しいnews.titleでコンポーネントのtitleプロパティが上書きされてしまうので、末尾のくエスチョンマークは消えてしまう。

値を変更する必要がある場合は、プロパティの値を基にdataやcomputed propertyを使って実装する必要がある。

 

図1 JavaScriptコンソールに表示されるwarning

 

4. 参考URL

上記のことは、以下のドキュメントを読めば理解できるはずだ。

https://jp.vuejs.org/v2/guide/components.html  のプロパティに関する部分。

https://jp.vuejs.org/v2/guide/components-props.html の特に単方向データフローの部分。

 


最終更新 2019/02/08 01:45:59 - kztomita
(2019/02/08 01:11:58 作成)
添付ファイル
warning.jpg - kztomita


リンク

その他のWiki
Linuxメモ
Xnuメモ

会社
(有)ビットハイブ
受託開発やってます。

よくやる仕事

・Webシステム開発(LAMP環境)
・Linuxサーバー設定関連
サーバー移転作業代行

開発事例にデジタルカタログ/マンガビューワーを追加しました。

検索

Adsense
最近のコメント