前提
vue-property-decorator
- TypeScript
やりたいこと
ただのチェックボックスをコンポーネント化して複数のページから使いたい。
やり方
大きく2ステップ。
Checkbox を親コンポーネントから渡した値を設定する。
子は prop を受け取るようにして。
@Component
export default class MyCheckbox extends Vue {
@Prop({ default: false }) checked
親はデータを渡すだけです。
<my-checkbox v-model="isChecked"></my-checkbox>
Checkbox の変更を親コンポーネントへ通知する。
emit を利用して更新された値を通知してあげます。
<input
id="checkbox"
type="checkbox"
:checked="checked"
@input="$emit('input', $event.target.checked)">
ハマったところ
チェックボックスの View が更新されない
^こういう状態が起きていました。value には true が設定されているが、チェックボックスに反映されていません。
v-model は :value
@input
のシンタックスシュガーという理解だったので :value="checked"
を設定していたのですが、チェックの状態を同期したいので正しくは :checked="checked"
でした。
警告が表示される
Vue には利用されるコンポーネント(子コンポーネント)は props で渡された値を変更してはいけないという原則があり警告が表示されます。
親コンポーネントへの通知は以下のように設定していました。
これでは props のデータを上書きしてしまいます。
@input="checked = $event.target.checked"
以下のように通知することで警告なしに同様の結果を得られることができました。
@input="$emit('input', $event.target.checked)"
まとめ
- checkbox の bool 値を制御したい場合は value ではなく checked を。
- input の変更を親に通知して値を変更したい場合は
$emit('input', xxx)
を利用する。
全体図
親
<template>
<div>
<my-checkbox v-model="isChecked" label="チェックボックス"></my-checkbox>
<p>設定された値:{{ isChecked }}</p>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import MyCheckbox from '~/components/MyCheckbox.vue'
@Component({
components: {
MyCheckbox
}
})
export default class index extends Vue {
isChecked = true
}
</script>
子
<template>
<div>
<label>{{ label }}
<input id="checkbox" type="checkbox" :checked="checked" @input="$emit('input', $event.target.checked)">
</label>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'
@Component
export default class MyCheckbox extends Vue {
@Prop({ default: false }) checked
@Prop() label
}
</script>
<style scoped>
/* 好きなスタイルを当てる */
</style>
参考
- https://jp.vuejs.org/v2/guide/components.html#%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%A8%E5%80%A4%E3%82%92%E9%80%81%E5%87%BA%E3%81%99%E3%82%8B
- https://jp.vuejs.org/v2/guide/components.html#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%A7-v-model-%E3%82%92%E4%BD%BF%E3%81%86