vue3 父子组件v-model传值方法总结

Vue父子组件v-model传值交互总结

概述

总结了Vue 3中父子组件之间使用v-model进行数据双向绑定的各种实现方式,包括普通类型和引用类型的处理。

文件结构

  • demo.vue - 父组件,使用v-model向子组件传递数据
  • child.vue - 子组件,接收父组件数据并支持双向绑定

父组件实现 (demo.vue)

vue 复制代码
<template>
  <div class="p-100px">
    <h1>{{ obj.count }}</h1>
    // 引用类型
    <Child v-model:obj="obj" />
    // 普通类型
    <Child v-model:count="count" />
  </div>
</template>

<script setup lang="ts">
import Child from '@/views/components/child.vue'
import { ref } from 'vue'

const count = ref(0)
const obj = ref({
  count: 0,
})
</script>

关键点:

  • 使用 v-model:obj="obj" 语法向子组件传递对象
  • 父组件维护响应式数据 obj

子组件实现方式

普通类型传值

方法1:使用 ref + watch
typescript 复制代码
import { ref, watch } from 'vue'
const props = defineProps({
  count: {
    type: Number,
    default: 0,
  },
})
const emit = defineEmits(['update:count'])
const count = ref(props.count)

watch(count, (newVal) => {
  emit('update:count', newVal)
})
方法2:使用 computed
typescript 复制代码
import { computed } from 'vue'
const props = defineProps({
  count: {
    type: Number,
    default: 0,
  },
})
const emit = defineEmits(['update:count'])
const count = computed({
  get: () => props.count,
  set: (value) => emit('update:count', value),
})
方法3:使用 defineModel (推荐)
typescript 复制代码
const count = defineModel('count')
方法4:使用 @vueuse/core
typescript 复制代码
import { useVModel } from '@vueuse/core'
const props = defineProps({
  count: {
    type: Number,
    default: 0,
  },
})
const count = useVModel(props, 'count')

引用类型传值

方法1:使用 ref + watch (深度监听)
typescript 复制代码
import { ref, watch } from 'vue'
const props = defineProps({
  obj: {
    type: Object,
    default: () => ({}),
  },
})
const emit = defineEmits(['update:obj'])
const obj = ref(props.obj)

watch(
  obj,
  (newVal) => {
    emit('update:obj', newVal)
  },
  { deep: true },
)
方法2:使用 defineModel (推荐)
typescript 复制代码
interface Obj {
  count: number
}

const obj = defineModel<Obj>('obj')

最佳实践建议

1. 优先使用 defineModel

  • Vue 3.4+ 版本推荐使用 defineModel
  • 代码更简洁,性能更好
  • 自动处理 props 和 emit

2. 引用类型处理

  • 对于对象类型,使用 defineModel 配合 TypeScript 接口
  • 确保类型安全,提供更好的开发体验

3. 命名规范

  • v-model 的自定义名称应该语义化
  • v-model:userInfov-model:formData

4. 类型定义

  • 使用 TypeScript 接口定义复杂对象类型
  • 提供更好的代码提示和类型检查

实际应用示例

当前项目中的实现展示了引用类型的双向绑定:

父组件传递:

vue 复制代码
<Child v-model:obj="obj" />

子组件接收:

vue 复制代码
<input type="text" class="border" v-model="obj.count" />

这种方式允许子组件直接修改父组件传递的对象属性,实现真正的双向数据绑定。

总结

Vue 3 提供了多种方式实现父子组件的双向数据绑定:

  1. defineModel - 最推荐的方式,简洁高效
  2. computed - 适合需要额外逻辑处理的场景
  3. ref + watch - 传统方式,适合复杂场景
  4. @vueuse/core - 第三方库,提供更多功能

选择合适的方式取决于具体需求和项目复杂度,但建议优先考虑 defineModel 方式。

相关推荐
AI浩1 小时前
【Labelme数据操作】LabelMe标注批量复制工具 - 完整教程
运维·服务器·前端
涔溪1 小时前
CSS 网格布局(Grid Layout)核心概念、基础语法、常用属性、实战示例和进阶技巧全面讲解
前端·css
2401_878454531 小时前
浏览器工作原理
前端·javascript
西陵2 小时前
为什么说 AI 赋能前端开发,已经不是选择题,而是必然趋势?
前端·架构·ai编程
by__csdn3 小时前
Vue3 setup()函数终极攻略:从入门到精通
开发语言·前端·javascript·vue.js·性能优化·typescript·ecmascript
天天扭码3 小时前
前端如何实现RAG?一文带你速通,使用RAG实现长期记忆
前端·node.js·ai编程
一条可有可无的咸鱼4 小时前
企业招聘信息,企业资讯进行公示
java·vue.js·spring boot·uni-app
Luna-player4 小时前
在前端中,<a> 标签的 href=“javascript:;“ 这个是什么意思
开发语言·前端·javascript
lionliu05194 小时前
js的扩展运算符的理解
前端·javascript·vue.js
小草cys4 小时前
项目7-七彩天气app任务7.4.2“关于”弹窗
开发语言·前端·javascript