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 来进行双向绑定。

相关推荐
醉城夜风~21 分钟前
CSS元素显示模式(display)
前端·css
AI大模型-小华1 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
做前端的娜娜子3 小时前
同一链接实现 PC Web 与移动 H5 自适应
前端·掘金·金石计划
小帅不太帅3 小时前
架构没变、规模没变,DeepSeek V4 Flash 正式版凭什么暴涨 47 分?
前端·aigc·deepseek
jarvisuni4 小时前
DeepSeekFlash前端依旧拉垮,而且变慢了很多!
前端·javascript·算法
卷福同学5 小时前
AI编程出海第二步:验证关键词能否做站
前端·人工智能·后端
先吃饱再说5 小时前
编写一个颜色选择器之后,我理解了 React 工程化的三层架构
react.js·前端框架·前端工程化
先吃饱再说5 小时前
别说你懂 useEffect:从底层机制到生命周期管理,这篇全讲透了
react.js·前端框架
赵庆明老师5 小时前
Vben精讲:21-详解web-antd:tsconfig.json
前端·json·vim