Nuxtで親コンポーネントから渡されるプロパティ(props)の変更を検出する

create
2021年04月02日
update
2021年04月02日

はじめに🥯

親コンポーネントから渡されたプロパティ(props)のデータが変更されたとき、それを検出してビューを更新したい。

string 型や number 型のデータならばなんの手間もいらず変更を検出してくれるが、オブジェクトや配列データでは一手間が必要になってくる。
その一手間について記事にしてみた。

Table 1. 環境
App Version

Nuxt.js

2.14.12

Nuxt(Vue) における変更検出の基本📝

Vue 公式のドキュメントに書いてある通り。

全てのコンポーネントには対応するウォッチャ(watcher)があり、コンポーネントのデータが変更されると setter がこのウォッチャに通知する。
そして通知を受け取ったウォッチャからコンポーネントの再描画が行われる。

watcher

このデータ変更を検出させるために注意すべきなのが

  • オブジェクトデータの変更

  • 配列データの変更

  • リアクティブなプロパティ

  • DOM操作をしたいとき

となる(詳細は公式のドキュメントや参考リンクを参照)。

props のオブジェクトデータの変更を検出する🔍

今回つまったのは、親コンポーネントから props オプションで渡されたオブジェクトデータの変更を検出する方法について。

検出可能にするには、ドキュメントより

  1. 親コンポーネントにおいてプロパティ値変更に vm.$set インスタンスメソッドを使う

  2. 親コンポーネントにおいて新しいオブジェクトとして生成し直す

という方法が考えられるが、いちいち親コンポーネントで上記のことを気にかけるのが面倒くさい。

よって今回は子コンポーネントにおいて、watch オプションを使って props のオブジェクトを監視させる。

監視プロパティ(watch)で変更を検出する

watch オプションで props のデータを監視し、変更に対して反応させる。
下記の例では nuxt-property-decorator ライブラリを利用しているので、代わりに @Watch デコレータを利用している。

Example 1. オブジェクトのプロパティを監視して変更を検出する
<script lang="ts">
import { Component, Prop, Vue, Watch } from 'nuxt-property-decorator'

@Component
export default class InputSearch extends Vue {
  /** 入力値 */
  message = ''

  /** URLクエリパラメータ */
  @Prop({ required: true, default: {} }) query!: Record<'tags', string>

  /** `query.tags` プロパティの変更を監視 */
  @Watch('query.tags', { immediate: true })   (1) (2) (3)
  onUpdateQueryTags() {   (4)
    this.message = this.query.tags?.toString() ?? ''
  }
}
</script>
1 watch オプションの代わりに @Watch デコレータを利用。
2 オブジェクトのプロパティを指定(ここでは query オブジェクトの tags プロパティ)して監視。
3 Vue インスタンスの初期化時にも処理を実行したいので immediate オプションを有効化。
4 変更を検出したときに実行する処理を定義。

オブジェクトのネストされているプロパティ全てを監視したい場合は deep オプションを有効化する。

@Watch('query', { immediate: true, deep: true })

おわりに😎

うっかりやらかす度合いが高そうなので、備忘録代わりに記事にしてみた。

props でオブジェクトそのまま渡すのは落とし穴ができやすくて怖いなーって思ったり。