($emit)Vue.js のプロパティを変更時の警告が出たときの対応

  • 2020年2月2日
  • 2020年2月2日
  • vue.js

Vue.jsで子コンポーネントのプロパティを変更しようとしたら警告(warn)が表示されたので対応法について記述したいと思います。

警告(warn)の内容

Element UIのDialogを使用して親コンポーネントから子コンポーネントにデータを渡す形でポップアップを表示させる実装をしていたら以下のようなエラーが表示されました。

Element – The world’s most popular Vue UI framework

Element,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的桌面端组件库

Avoid mutating a prop directly since 
the value will be overwritten whenever 
the parent component re-renders. 
Instead, use a data or computed property based on the prop's value.
 Prop being mutated: "dialogVisible"

子コンポーネントで直接データを書き換えるのではなくpropsで受け取ったデータを使ってくださいという警告のようです。ポップアップを閉じる時にデータが適切に親コンポーネントに渡されていないため、このようなエラーが表示されるようです。この警告をなくすためには親から子コンポーネントで受け取ったデータを適切に親コンポーネントに返す必要があります。

$emit

子から親にデータを渡す際には$emitを使用します。$emitを使用すると子コンポーネントから親コンポーネントのメソッドを呼び出してデータを渡すことができます。

$emit( eventName, […args] )
  • 親から小(Props)
  • 子から親(Emit)

今回、親コンポーネントを(Index.vue)、子コンポーネントを(Dialog.vue)としてコードを記述していきます。。Element Uiを使ったポップアップの開閉はdialogVisibleを使い、デフォルト値はFalseです。

ユーザーがMoreボタンをクリックするとdialogVisibleの値がTrueに変更になり、ポップアップが表示されます。

 Index.vue
<el-button :data="professors"  dialogVisible=true">
More...
</el-button>

子コンポーネントのDialogには:dialogVisible=”this.dialogVisible”を記述して親から子にデータを渡してあげます。

Index.vue

 <!-- Modal   -->
      <Dialog 
        :dialogVisible="this.dialogVisible" 
         :professor="this.professor" 
      />

data () {
    return {
      professors : [],
      professor : {},
      dialogVisible : false,
      activeName: 'first',
      search: ''
    }
  },

親コンポーネントのIndex.vueから渡されたdialogVisibleのデータをpropsを使いTypeを指定してあげて受け取ってあげます。Moreボタンをクリックしてポップアップが表示されている状態なので、dialogVisibleの値はTrueのままですね。ポップアップを閉じる際にemitを使わずにdialogVisibleのデータをfalseにすると警告が表示されます。

Dialog.vue

<template>
  <div>
      <el-dialog 
        title="Status"
        :visible.sync="dialogVisible"
        width="90%"
        top="8vh"
        custom-class="modal"
      > 
</el-dialog >
  </template>
  </div>
props: {
    'dialogVisible': {
       type: Boolean,
       required: true
    },
    'professor': {
       type: Object,
       required: true
    }
  },

それを避けるためにDialogコンポーネントに:before-closeを追加してあげます。:before-closeはElement UIのdialogにある機能でダイアログを閉じる直前の処理を実装できます。 methodsにemitを追加してイベント発火を親に伝えてあげます。今回、$emitのイベント名をchangeVisivle、引数をfalseとします。

dialog.vue
<el-dialog 
   title="Status" 
    :visible.sync="dialogVisible" 
    width="90%"        
    top="8vh"        
    custom-class="modal"        
    :before-close="hideModal"  
>   

methods: {
    hideModal() {
      this.$emit('changeVisivle', false)
    }
  },
Index.vue
<Dialog 
     :dialogVisible="this.dialogVisible" 
      :professor="this.professor" 
      @changeVisivle="handler"
      />
methods: {
   handler(changeVisivle) {
      this.dialogVisible = changeVisivle
    }
 }

$emitのイベント名と引数をIndex.vueで受け取ってあげて、methods内でthis.dialogVisible = changeVisivleを記述することで子から親にデータを適切に渡すことができ、警告の表示も無くなります。

>文系エンジニア大学生の技術ブログ

文系エンジニア大学生の技術ブログ

社会が多様化していく中、大学生の学生生活も多様であるべきと考えています。主にエンジニア向けにITやプログラミングなどの技術系と大学生向けに休学、留学、海外生活、トビタテ留学、長期インターンに関する記事を書いています。