✌️
Vue3の双方向バインディングv-modelを使ってみる
abstract
Vue2では、親子間の双方向バインディングは.sync
が利用されている。
Vue3からは.sync
が廃止されてv-model:hoge
に変わる。
その使い方
.syncとは
こんなの
<text-document v-bind:title.sync="doc.title"></text-document>
.sync
をさらにほぐすとこんな感じになる。
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
.syncの使い方はこちら
v-modelに変えてみる
Vue3の双方向バインディング
<text-document v-model:title="doc.title"></text-document>
簡単に置き換えられる。
親子間で監視する
作るもの
親と子のコンポーネントでそれぞれinputを用意してバインディングさせてみる。
親コンポーネント
Parent.vue
<template>
<div>
<p>parent</p>
<input type="text" v-model="titleComputed" />
<ChildInput v-model:title="titleComputed" />
</div>
</template>
<script>
import { computed, defineComponent, ref } from 'vue'
import ChildInput from './Child.vue'
export default defineComponent({
name: 'ParentInput',
components: {
ChildInput,
},
setup() {
const title = ref('')
const titleComputed = computed({
get: () => title.value,
set: (value) => (title.value = value),
})
return {
titleComputed,
}
},
})
</script>
子コンポーネント
<template>
<div>
<p>child</p>
<input type="text" v-model="titleComputed" />
</div>
</template>
<script>
import { defineComponent, toRefs, computed } from 'vue'
export default defineComponent({
name: 'ChildInput',
components: {
GrandChild,
},
props: {
title: String,
},
emits: ['update:title'],
setup(props, { emit }) {
const { title } = toRefs(props)
const titleComputed = computed({
get: () => title.value,
set: (value) => {
emit('update:title', value)
},
})
return {
titleComputed,
}
},
})
</script>
わー
孫も追加してみる
蛇足で三世代バインディングを作ってみる。
子コンポーネントを編集
Child.vue
<template>
<div>
<p>child</p>
<input type="text" v-model="titleComputed" />
+ <GrandChild v-model:title="titleComputed" />
</div>
</template>
<script>
import { defineComponent, toRefs, computed } from 'vue'
+import GrandChild from './GrandChild.vue'
export default defineComponent({
name: 'ChildInput',
components: {
GrandChild,
},
props: {
title: String,
},
emits: ['update:title'],
setup(props, { emit }) {
const { title } = toRefs(props)
const titleComputed = computed({
get: () => title.value,
set: (value) => {
emit('update:title', value)
},
})
return {
titleComputed,
}
},
})
</script>
孫コンポーネント追加
<template>
<div>
<p>grand child</p>
<input type="text" v-model="titleComputed" />
</div>
</template>
<script>
import { computed, defineComponent, toRefs } from 'vue'
export default defineComponent({
props: { title: null },
emits: ['update:title'],
setup(props, { emit }) {
const { title } = toRefs(props)
const titleComputed = computed({
get: () => title.value,
set: (value) => emit('update:title', value),
})
return {
titleComputed,
}
},
})
</script>
わあー
参考:https://qiita.com/ponko2bunbun/items/d05d90bc10be61c0e3af#comments
Discussion