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を記述することで子から親にデータを適切に渡すことができ、警告の表示も無くなります。