Vue.jsのpropsで理解が甘かったことがあるので備忘録として
はじめに
親のコンポーネントから子のコンポーネントに値を渡す際、props プロパティとして渡すが、そのリアクティブ性について学んだ。
単方向データフロー (One way Data Flow)
基本的に、リアクティブに変化する流れ、データーフローは親から子に流れるのみで、子から親に流れることはない。
子が親からもらったプロパティを変化させようとしてもエラーが出る。
もし、親からもらったデータを変化させたいなら2つの方法があり、
- 子のコンポーネントでローカルのデータとして使う
ローカルのデータの初期値としてプロパティを扱う。
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
- プロパティを算出プロパティで使う
特に加工する必要が無いなら算出プロパティで扱うこともできる。
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
例外
ただし例外がある
配列とオブジェクト
である。
JavaScript のオブジェクトや配列は参照渡しなので、プロパティが配列やオブジェクトの場合、子コンポーネント内でオブジェクトや配列自体を変更すると、親の状態に 影響してしまい、Vue はこれに対して警告できないことに注意してください。一般的なルールとして、オブジェクトや配列を含むプロパティの変更は避けるべきです。これは単方向のデータバインディングが無視されてしまい、望ましくない結果を引き起こす可能性があるからです。
配列とオブジェクトは参照渡しなため、子のコンポーネントで変更しても、親のコンポーネントに変更は反映される。
ただこれは単方向にするのに必要以上にコストがかかってしまうため仕方なく公式がそのままにしただけで、どちらにせよ子コンポーネントが親コンポーネントの状態を変えられるのは、コードリーディングをしづらくするので避けるべき。
基本的には子コンポーネントはイベントとemitでのやりとりが理想。
最後に
単方向データフロー自体は理解していても、配列とオブジェクトという例外があることを知らなかったことで、かなり困惑していたが、今回学習したことでかなりすっきりしました。
参考