一文极简了解 Vue3 父子组件的 v-model 双向绑定
自从使用 Vue3 做前端,就一直被这个问题困扰着。无论是官方文档,还是网上的文章教程,都说的不够通俗易懂。
我一直也是迷迷糊糊的用着,反正页面能跑就行了,这次彻底把这个逻辑搞明白。
这篇文章不说任何底层技术,也不说双向绑定、单向绑定、数据流向这样的概念解释,咱就用代码去解释,一切都在注释中。
父组件代码
<template>
<div>
<!-- 双向绑定 visible -->
<!-- 非双向绑定 count,需要使用 @update-count 绑定更新事件 -->
<Camera v-model:visible="cameraVisible" :count="cameraCount" @update-count="handleCountUpdate" />
</div>
</template>
<script setup>
import { ref } from 'vue'
const cameraVisible = ref(false)
const cameraCount = ref(0)
function handleCountUpdate(newCount) {
cameraCount.value = newCount
}
</script>
子组件代码
<template>
<el-dialog v-model="visible" @close="handleClose">
<button @click="incrementCount">Increment Count</button>
</el-dialog>
</template>
<script setup>
import { ref, watch } from 'vue'
// 通过 props 接收父组件传过来的值
const props = defineProps({
visible: boolean,
count: number
})
// 使用 defineEmits 声明子组件可以发送的事件
// visible 是双向绑定的数据,因此使用 update: 事件,这里需要和父组件 props 名称相同
// count 是非双向绑定的数据,使用自定义事件(事件名称可以自定义,如:update-count1、update-count2)
const emit = defineEmits(['update:visible', 'update-count'])
// 将 props 接收到的值转换为本地响应式数据,方便子组件使用
const visible = ref(props.visible)
const count = ref(props.count)
// 监听父组件 visible 的值,如果父组件值变化,同步更新本地响应式数据
watch(() => props.visible, (newVal) => {
visible.value = newVal
})
// 监听本地响应式数据的变化,发送 update:visible 事件,由于是双向绑定,父组件的值会直接改变。这里传递的 visible 是 ref 对象,可以直接传递,Vue 自动解包数据,也可使用 () => visible.value
watch(visible, (newVal) => {
emit('update:visible', newVal)
})
// 同上
watch(() => props.count, (newVal) => {
count.value = newVal
})
// 逻辑同上,但 count 是非双向绑定,因此父组件需要做额外处理以更新父组件的值
watch(count, (newVal) => {
emit('update-count', newVal)
})
// 子组件在不同情况下修改 visible 和 count 的值
function handleClose() {
visible.value = false
}
function incrementCount() {
count.value++
}
</script>
小结
- 双向绑定不局限于单个值,哪些数据使用双向绑定视需求而定,看明白了上面的代码,可再深入了解双向绑定和非双向绑定的区别
- 无论是否双向绑定,子组件均需要使用 emit 向父组件发送数据,唯一不同的是父组件接收数据的方式
以上。