React 和 Vue3 在事件传递的区别

最近用React19写了一个笔记应用,发现React和Vue3 在 事件传递 方式上不一样:

React :父组件定义方法,作为 props 传递给子组件,子组件在合适的时候调用这些方法(由父组件控制逻辑)

Vue3:子组件使用 defineEmits 触发事件,父组件监听事件并执行对应的回调函数(由子组件通知父组件)

最近写的笔记应用,我们以这个搜索组件来举例React和Vue的区别

React事件传递方式

在React中,父组件通过props(属性)向子组件传递数据和事件处理函数,使得子组件能够与父组件通信。我们以上面截图的搜索框组件为例,其中父组件传递了多个事件处理函数(onChange、handleSearch、onClearSearch)到子组件。

父组件

tsx 复制代码
import React, { useState } from 'react'
import SearchBar from './SearchBar'

const ParentComponent = () => {
  const [searchQuery, setSearchQuery] = useState('')
  // 处理搜索逻辑
  const handleSearch = () => {
    console.log('搜索:', searchQuery)
  }
  
  // 清空搜索框
  const onClearSearch = () => {
    setSearchQuery('')
  }
  
  return (
   <SearchBar
     value={searchQuery}
     onChange={({ target }) => setSearchQuery(target.value)}
     handleSearch={handleSearch}
     onClearSearch={onClearSearch}
     />
  )
}
export default ParentComponent

示例:子组件(SearchBar.tsx),样式用了tailwindcss v4

tsx 复制代码
import React from 'react'
import { FaMagnifyingGlass } from 'react-icons/fa6'
import { IoMdClose } from 'react-icons/io'

interface SearchBarProps {
  value: string
  onChange: (event: React.ChangeEvent<HTMLInputElement>) => void
  handleSearch: () => void
  onClearSearch: () => void
}

const SearchBar: React.FC<SearchBarProps> = ({
  value,
  onChange,
  handleSearch,
  onClearSearch,
}) => {
  return (
    <div className="w-80 flex items-center px-4 bg-slate-100 rounded-md">
      <input type="text" placeholder="搜索笔记"
          className="w-full text-xs bg-transparent py-[11px] outline-none"
          value={value}
          onChange={onChange} // 触发父组件的onChange方法
        />
       {value && (
          <IoMdClose 
            className="text-xl text-slate-500 cursor-pointer hover:text-black mr-3"
            onClick={onClearSearch} // 触发父组件的 handleSearch方法
            />
        )}
        <FaMagnifyingGlass
            className="text-slate-400 cursor-pointer hover:text-black"
            onClick={handleSearch} // 触发父组件的handleSearch方法
         />
     </div>
  )
}
export default SearchBar
事件传递过程分析
  1. 父组件定义方法
  • handleSearch(): 处理搜索逻辑
  • onClearSearch(): 清空搜索框
  • onChange(): 更新输入框内容
  1. 父组件通过props把这些方法传递给子组件
tsx 复制代码
<SearchBar
 value={searchQuery}
 onChange={({ target }) => setSearchQuery(target.value)}
 handleSearch={handleSearch}
 onClearSearch={onClearSearch}
/>
  1. 子组件SearchBar接受props并在事件触发时调用这些方法
  • 当输入框内容变化时,触发onChange(event), 更新searchQuery
  • 当点击放大镜图标时,调用handleSearch,执行搜索
  • 当点击关闭按钮时,调用onClearSearch,清空搜索框
  1. 为什么要这样做?
  • 父组件控制数据状态,子组件只是一个UI组件(受控组件)
  • 子组件无需管理数据,它只是接受value和事件处理函数
  • 代码更清晰,可复用性更高,不同地方的搜索框可以使用相同的SearchBar组件
  1. 总结
    ✅ 父组件定义事件方法,并通过 props 传递给子组件
    ✅ 子组件调用 props 里的方法 来通知父组件(例如 onChange、handleSearch、onClearSearch)
    ✅ 父组件负责管理状态,子组件只是一个展示组件
Vue3事件传递方式

在Vue3中,子组件不会调用父组件的方法,而是通过emit事件方式通知父组件,父组件在模板中监听该事件并执行回调。

父组件

vue 复制代码
<script setup>
import { ref } from 'vue'
import SearchBar from './SearchBar.vue'

const searchQuery = ref('')
// 监听子组件的事件
const handleSearch = () => {
  console.log('搜索:', searchQuery.value)
}

const onClearSearch = () => {
  searchQuery.value = ''
}
</script>

<template>
  <SearchBar
    v-model="searchQuery"
    @search="handleSearch"
    @clear="onClearSearch"
   />
</template>

子组件 SearchBar.vue

vue 复制代码
<script setup>
import { defineEmits, defineProps } from 'vue'

const props = defineProps({
  modelValue: String,
})

const emit = defineEmits(['update:modelValue', 'search', 'clear'])

const handleInput = (event) => {
  emit('update:modelValue', event.target.value) // 触发 v-model
}

const handleSearch = () => {
  emit('search') // 触发 search 事件
}

const handleClear = () => {
  emit('update:modelValue', '') // 触发 v-model 清空输入框
  emit('clear') // 触发 clear 事件
}
</script>

<template>
  <div class="search-bar">
    <input
      type="text"
      :value="modelValue"
      @input="handleInput"
      placeholder="搜索笔记"
    />
    <button v-if="modelValue" @click="handleClear">清空</button>
    <button @click="handleSearch">搜索</button>
  </div>
</template>

上面的子组件我们可以用3.4版本的defineModel简化下代码,

vue 复制代码
<script setup>
import { defineEmits } from 'vue'

const model = defineModel()
const emit = defineEmits(['search', 'clear'])
const handleSearch = () => {
  emit('search') // 触发 search 事件
}

const handleClear = () => {
  model.value = ''
  emit('clear') // 触发 clear 事件
}
</script>

<template>
  <div class="search-bar">
    <input
      type="text"
      v-model="model"
      placeholder="搜索笔记"
    />
    <button v-if="model" @click="handleClear">清空</button>
    <button @click="handleSearch">搜索</button>
  </div>
</template>
对比项 React (父传子) Vue 3 (emit 子传父)
事件触发方式 子组件调用父组件的 props 方法 子组件 emit 事件,父组件监听
状态管理方式 父组件控制状态,通过 props 传递 子组件通知父组件,父组件修改数据
v-model 实现 需要 useState + onChange defineProps + defineEmits
灵活性 父组件完全控制,代码可读性更高 子组件可独立触发事件,但需要 emit
总结
  1. React 是 "父组件控制子组件"

    • 逻辑和状态都在父组件

    • 子组件只调用 props 传递的方法,不需要管理状态

  2. Vue 3 是 "子组件通知父组件"

    • 子组件使用 emit 触发事件

    • 父组件监听事件并修改状态(比如 v-model)

两者设计理念不同,但都能够实现组件间的通信,React 更强调单向数据流 ,而 Vue 3 更灵活,支持 v-model 和 emit 来进行双向绑定。

相关推荐
uhakadotcom18 分钟前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom22 分钟前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom24 分钟前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom33 分钟前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom43 分钟前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试
LaoZhangAI2 小时前
2025最全GPT-4o图像生成API指南:官方接口配置+15个实用提示词【保姆级教程】
前端
ONE_Gua2 小时前
chromium魔改——CDP(Chrome DevTools Protocol)检测01
前端·后端·爬虫
LaoZhangAI2 小时前
2025最全Cherry Studio使用MCP指南:8种强大工具配置方法与实战案例
前端
咖啡教室2 小时前
前端开发日常工作每日记录笔记(2019至2024合集)
前端·javascript
溪饱鱼2 小时前
Nuxt3能上生产吗?
前端