20
8

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 3 years have passed since last update.

Vuetifyによる子コンポーネントと親コンポーネント間の双方向データ受け渡しの話

Last updated at Posted at 2019-08-22

本記事について

下記問題に当たった人向けにv-modelと$emitを使った解決方法を記載してます。

  • Vuetifyを使った子コンポーネントと親コンポーネント間のデータ受け渡しで困った方
  • 双方向データ受け渡しを実装したけど、「Vue warn]: Avoid mutating a prop directly since ~」って出ちゃった人

問題

例えば、<v-navigation-drawer>をの開閉Toggleを親コンポーネント内で作成したく下記のような実装をしたとする。

  • 子コンポーネント
AppNavigationDrawer.vue
<template>
  <v-navigation-drawer
    v-model="drawer"
    absolute
    temporary
  >
  </v-navigation-drawer>
</template>
<script>
  export default {
    props: {
      drawer: {
        type: Boolean,
        default: false
      }
    }
  }
</script>
  • 親コンポーネント
AppHeader.vue
<template>
  <v-app-bar>
    <v-app-bar-nav-icon
      @click.stop="drawer = !drawer"
    />
  </v-app-bar>
 <navigation-drawer
   v-model="drawer"
 />
</template>
<script>
import NavigationDrawer from '@/components/AppNavigationDrawer'

export default {
  components: {
    AppNavigationDrawer
  },
  data () {
    return {
      drawer: false
    }
  }
}
</script>

結果、子コンポーネント側のdrawerが変化するような操作、例えばNavigationの外側をクリックをすると下記のようなエラーが出る。
スクリーンショット 2019-08-22 16.34.38.png
propsを直接変更するんじゃねぇ!っていうアラートですね。

解決方法

直接変更がダメならemitを使えばいいじゃない。つまり、この辺の話をVuetify Componentに応用すれば良いだけ。

  • 子コンポーネント
AppNavigationDrawer.vue
<template>
  <v-navigation-drawer
    :value="value"
    absolute
    temporary
    @input="$emit('input', $event)"
  >
  </v-navigation-drawer>
</template>
<script>
  export default {
    props: {
      value: {
        type: Boolean,
        default: false
      }
    }
  }
</script>
  • 親コンポーネント
AppHeader.vue
<template>
  <v-app-bar>
    <v-app-bar-nav-icon
      @click.stop="drawer = !drawer"
    />
  </v-app-bar>
 <navigation-drawer
   v-model="drawer"
 />
</template>
<script>
import NavigationDrawer from '@/components/AppNavigationDrawer'

export default {
  components: {
    AppNavigationDrawer
  },
  data () {
    return {
      drawer: false
    }
  }
}
</script>

親からのprops valueを<v-navigation-drawer></v-navigation-drawer>の開閉状態であるvalueにbindする。
子の変化は自身のinput event契機で、親のinputイベントを$emitすることで親コンポーネントへ変化を伝播する。

eventとvalueが定義されているVuetifty Componentであれば何でも応用できそうです。

20
8
1

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
20
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?