LoginSignup
4
4

More than 3 years have passed since last update.

[Vue.js]propsは単方向のデータフロー?場合によってそうでもない

Posted at

単方向のデータフローは何か

全てのプロパティは、子プロパティと親プロパティの間に、 単方向のバインディング を形成します: 親のプロパティが更新されると、子へと流れ落ちていきますが、それ以外の方法でデータが流れることはありません。これによって、子コンポーネントが誤って親の状態を変更することがなく、これによって、アプリのデータフローを 理解しづらい 可能性のある子コンポーネントによる誤った親の状態変更から、防ぎます.....。----vue.js公式ドキュメントより

具体例を見てみましょう

下記の様に親コンポーネント(Parent)と子コンポーネント(Child)が存在します

parent.vue
<template>
  <div id="app">
    <child :msg="msg"></child>
  </div>
</template>

<script>
import Child from './components/Child.vue'

export default {
  name: 'parent',
  data: function () {
    return{
      msg:'ご飯だよ'
    }
  },
  components: {
    Child
  }
}
</script>
<style>
</style>
Child.vue
<template>
  <div class="hello">
    <p>{{msg}}</p>
  </div>
</template>

<script>
export default {
  name: 'child',
  props:[ 'msg' ],
}
</script>

<style scoped>
</style>

parent.vueからプロパティーmsgをChild.vueに渡しています、何の問題もありません
キャプチャ.PNG
ここでChild.vueに一つのクリックイベントを追加します

Child.vue
<template>
  <div class="hello">
    <p>{{msg}}</p>
<!--追加-->
    <button @click="childMsg">食べたくない</button>
  </div>
</template>

<script>
export default {
  name: 'child',
  props:[ 'msg' ],
//追加
  methods:{
    childMsg:function () {
      this.msg = '食べたくない'
    }
  }
}
</script>

<style scoped>

</style>

実際クリックしたら,parent.vueから渡された値は変換しましたが警告も一つ出てます
キャプチャ.PNG
訳すと
親コンポーネントが再レンダリングされるたびに値が上書きされるため、propsを直接変更しないでください。
Child.vueで値を上書きしようとしても、結局画面再度読み込みすれば、また値が元に戻ってしまう,parent.vueで定義された値を影響出来ません,公式ドキュメントが書いた通りで結果ですね

単方向のデータフローではない場合

JavaScript のオブジェクトと配列は、参照渡しされることに注意してください。参照として渡されるため、子コンポーネント内で配列やオブジェクトを変更すると、 親の状態へと影響します。---vue.js公式ドキュメント

具体例を見てみます

parent.vue
<template>
  <div id="app">
    <child :messge="messge"></child>
  </div>
</template>

<script>
import Child from './components/Child.vue'

export default {
  name: 'parent',
  data: function () {
//オブジェクトプロパティーに修正
    return{
      messge:{msg:'ご飯だよ'}
    }
  },
  components: {
    Child
  }
}
</script>

<style>

</style>
Child.vue
<template>
  <div class="hello">
    <p>{{messge.msg}}</p>
    <button @click="clickFunction">食べたくない</button>
  </div>
</template>

<script>
export default {
  name: 'child',
  props:[ 'messge' ],
//イベント追加
  methods:{
    clickFunction:function () {
      this.messge.msg = '食べたくない'
    }
  }
}
</script>

<style scoped>

</style>

キャプチャ.PNG

この場合データ変換しても、警告はされません

結論

警告されない理由は与えるプロパティーのtypeと関係してます,もしプロパティーがArrayあるいはObjectの場合,親コンポーネントから子コンポーネントに渡すのはプロパティーのindexになります,つまりコンポーネントの間でプロパティーを共有してる形になります。

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