Vue3 父子组件传参通信的完整指南

更新日期: 2025-10-23 阅读: 17 标签: 通信

vue 开发中,组件化是重要的开发方式。但组件之间经常需要共享数据和交互,这时候组件通信就变得很关键。父子组件通信是最常用的场景,比如按钮组件点击后要通知父组件,或者表单组件需要从父组件获取数据。


Props:父组件向子组件传递数据

Props 是父组件向子组件传递数据的主要方式。可以把 Props 想象成函数的参数,父组件传递数据,子组件接收数据。

父组件传递数据的方法:

<template>
  <ChildComponent :message="parentMessage" :count="totalCount" />
</template>

<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'

const parentMessage = ref('来自父组件的消息')
const totalCount = ref(10)
</script>

子组件接收数据的方法:

<template>
  <div>
    <p>{{ message }}</p>
    <p>计数器:{{ count }}</p>
  </div>
</template>

<script setup>
// 定义 Props
const props = defineProps({
  message: {
    type: String,
    required: true
  },
  count: {
    type: Number,
    default: 0
  }
})
</script>

Props 的特点:

  • 单向数据流:数据只能从父组件传到子组件

  • 类型检查:可以指定接收的数据类型

  • 默认值:可以设置默认值

  • 必需性:可以标记某些 Props 必须传递


自定义事件:子组件向父组件通信

当子组件需要向父组件传递信息时,可以使用自定义事件。这种方式让子组件能够通知父组件发生了某些事情。

子组件触发事件的方法:

<template>
  <button @click="handleClick">点击按钮</button>
  <input :value="inputValue" @input="handleInput" />
</template>

<script setup>
import { ref } from 'vue'

const emit = defineEmits(['button-clicked', 'input-changed'])
const inputValue = ref('')

const handleClick = () => {
  emit('button-clicked', '按钮被点击了')
}

const handleInput = (event) => {
  inputValue.value = event.target.value
  emit('input-changed', inputValue.value)
}
</script>

父组件监听事件的方法:

<template>
  <ChildComponent 
    @button-clicked="handleButtonClick"
    @input-changed="handleInputChange"
  />
</template>

<script setup>
import ChildComponent from './ChildComponent.vue'

const handleButtonClick = (message) => {
  console.log('收到子组件的消息:', message)
}

const handleInputChange = (newValue) => {
  console.log('输入框内容变了:', newValue)
}
</script>


v-model:简化双向数据绑定

v-model 是 Props 和自定义事件的简化写法,让双向数据绑定更简单。

传统写法(使用 Props + 事件):

<!-- 父组件 -->
<template>
  <CustomInput 
    :modelValue="searchText"
    @update:modelValue="newValue => searchText = newValue"
  />
</template>

<!-- 子组件 -->
<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

使用 v-model 的简洁写法:

<!-- 父组件 -->
<template>
  <CustomInput v-model="searchText" />
</template>

<!-- 子组件 -->
<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>

Vue3 支持多个 v-model 绑定:

<!-- 父组件 -->
<template>
  <UserForm 
    v-model:name="userName"
    v-model:email="userEmail"
    v-model:age="userAge"
  />
</template>

<!-- 子组件 -->
<template>
  <input :value="name" @input="$emit('update:name', $event.target.value)" />
  <input :value="email" @input="$emit('update:email', $event.target.value)" />
  <input :value="age" @input="$emit('update:age', $event.target.value)" />
</template>

<script setup>
defineProps(['name', 'email', 'age'])
defineEmits(['update:name', 'update:email', 'update:age'])
</script>


使用 Props 的注意事项

设计 Props 时要遵循这些原则:

  • 保持简单:避免传递复杂的对象

  • 明确接口:使用 TypeScript 或详细定义 Props

  • 合理默认值:为可选 Props 提供合适的默认值

常见问题处理:

问题1:直接修改 Props

<!-- 错误做法 -->
<script setup>
const props = defineProps(['user'])
props.user.name = '新名字' // 这样会报错!
</script>

<!-- 正确做法 -->
<script setup>
const props = defineProps(['user'])
const localUser = ref({ ...props.user })
localUser.value.name = '新名字' // 这样可以
</script>

问题2:监听深层 Props 变化

<script setup>
import { watch } from 'vue'

const props = defineProps(['config'])

// 监听整个 config 对象的变化
watch(
  () => props.config,
  (newConfig) => {
    console.log('配置发生变化', newConfig)
  },
  { deep: true }
)
</script>


性能优化建议

减少不必要的重新渲染:

<script setup>
import { computed } from 'vue'

const props = defineProps(['items', 'filter'])

// 使用 computed 缓存计算结果
const filteredItems = computed(() => {
  return props.items.filter(item => 
    item.name.includes(props.filter)
  )
})
</script>

控制事件触发频率:

<script setup>
import { ref } from 'vue'

const emit = defineEmits(['search'])
const searchText = ref('')

// 防抖搜索,避免频繁触发事件
let timeoutId
const handleSearch = (value) => {
  searchText.value = value
  clearTimeout(timeoutId)
  timeoutId = setTimeout(() => {
    emit('search', searchText.value)
  }, 300)
}
</script>


组合式 api 的优势

Vue3 的组合式 API 让组件通信更灵活:

<script setup>
import { useCart } from '../composables/useCart'

// 在多个组件中共享相同的业务逻辑
const { cartItems, addToCart, removeFromCart } = useCart()
</script>


实际应用场景

  1. 表单组件:父组件传递初始值,子组件在用户输入时通过事件更新数据

  2. 列表组件:父组件传递列表数据,子组件在操作项时通过事件通知父组件

  3. 模态框组件:父组件控制显示状态,子组件在关闭时通过事件通知父组件


调试技巧

在开发过程中,可以使用这些方法调试组件通信:

<script setup>
// 在子组件中打印 Props
const props = defineProps({...})
console.log('收到的 Props:', props)

// 监听事件触发
const emit = defineEmits(['my-event'])
const handleAction = () => {
  console.log('准备触发事件')
  emit('my-event', data)
}
</script>


总结

父子组件通信是 Vue 开发的基础。掌握 Props、自定义事件和 v-model 的使用方法,能够帮助你构建复杂的应用程序。根据具体场景选择合适的方法,可以让代码更清晰、更易维护。

记住这些要点:

  • 数据流从父组件到子组件使用 Props

  • 子组件向父组件传递信息使用自定义事件

  • 双向数据绑定使用 v-model

  • 复杂的业务逻辑可以使用组合式 API 抽离

通过合理使用这些通信方式,你可以创建出结构清晰、易于维护的 Vue 应用程序。

本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!

链接: https://fly63.com/article/detial/13040

vue.js $emit/$on的用法和理解_vue组件之间数据传输通信

每个 Vue 实例都实现了事件接口vm.$emit( event, arg ) 触发当前实例上的事件;vm.$on( event, fn )监听event事件后运行。实例说明:Vuejs 用$emit与$on来进行兄弟组件之间的数据传输通信,Vuejs 用$emit与$on来进行跨页面之间的数据传输通信

两个浏览器窗口间通信总结

两个浏览器窗口间通信:一个窗口更新localStorage,另一个窗口监听window对象的storage事件来实现通信;所有的WebSocket都监听同一个服务器地址,利用send发送消息,利用onmessage获取消息的变化;借助iframe 或 window.open;HTML5 中的 Web Worker 可以分为两种不同线程类型

前端跨页面通信,你知道哪些方法?

在浏览器中,我们可以同时打开多个Tab页,每个Tab页可以粗略理解为一个“独立”的运行环境,即使是全局对象也不会在多个Tab间共享。然而有些时候,我们希望能在这些“独立”的Tab页面之间同步页面的数据、信息或状态。

Vue组件之间通信的七种方式

使用Vue也有很长一段时间,但是一直以来都没对其组件之间的通信做一个总结,这次就借此总结一下。父子组件之间的通信props和$emit 父组件通过props将数据下发给props

浏览器标签页之间通信的实现

前端开发过程中,总是避免不了要进行前端标签页之间的通信,最经典的例子莫过于音乐播放网站中,当第一次点击播放列表中的歌曲时,它会打开一个新的标签页进行播放,而当在列表中再次点击歌曲播放时

基于 ThinkJS 的 WebSocket 通信详解

我们的项目是基于 ThinkJS + Vue 开发的,最近实现了一个多端实时同步数据的功能,所以想写一篇文章来介绍下如何在 ThinkJS 的项目中利用 WebSocket 实现多端的实时通信。ThinkJS 是基于 Koa 2 开发的企业级 Node.js 服务端框架

Socket是如何通信的?

其实服务器的处理和客户端大同小异,分三个逻辑分支:检索成功,用检索到的Socket来处理接收报文;检索失败,服务器侦听(listen)目的端口,创建全新的Socket服务客户;检索失败,服务器没有侦听目的端口,丢弃处理

vue中使用v-model完成组件间的通信

如何实现两个组件之间的双向传递呢?即,在父组件中修改了值,子组件会立即更新。在子组件中修改了值,父组件中立即更新。vue中有一个很神奇的东西叫v-model,它可以完成我们的需求。

vue父子组件通信高级用法

vue项目的一大亮点就是组件化。使用组件可以极大地提高项目中代码的复用率,减少代码量。但是使用组件最大的难点就是父子组件之间的通信。父组件通过$refs调用子组件的方法。 以上就是父子组件通信的方式

微服务的三种通信方法

在微服务架构的世界中,我们通过一系列服务构建应用。集合中的每项服务都符合以下标准:松散耦合、可维护和可测试、可以独立部署,微服务架构中的每个服务都解决了应用中的业务问题

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!