Skip to content

React 核心与 Vue/React 对照

设计哲学 · 生命周期 · Hooks · 写法对照 · 合成事件


一、React vs Vue 设计哲学

  • 开发模式:React:JSX 开发模式;Vue:模板语法开发模式
  • 智能依赖收集:React useEffect 需手动加依赖;Vue3 watchEffectcomputed 自动收集
  • React 心智负担:闭包陷阱(过时变量)、依赖选择、重复渲染、hooks 必须顶层调用
  • 根源:React 每次组件渲染,所有代码被重新调用一次

二、React 生命周期(类组件)

阶段生命周期说明
挂载constructor初始化 state,绑定方法
挂载static getDerivedStateFromPropsprops→state 映射,无 this
挂载render渲染 JSX(纯函数)
挂载componentDidMountDOM 已挂载,发起 AJAX 请求
更新shouldComponentUpdate控制是否重新渲染(性能优化)
更新getSnapshotBeforeUpdateDOM 更新前捕获信息(如滚动位置)
更新componentDidUpdateDOM 已更新,可操作 DOM
卸载componentWillUnmount清除定时器、取消订阅
错误getDerivedStateFromError渲染阶段捕获错误,返回降级 UI
错误componentDidCatch记录错误日志

被废弃的三个方法componentWillMountcomponentWillReceivePropscomponentWillUpdate 因 Fiber 异步渲染可能被重复调用,React 16.3 起标记 UNSAFE_


三、Vue vs React 生命周期对比

功能Vue2Vue3 (setup)React (类)React (函数)
创建前beforeCreatesetup()constructor函数体执行
挂载后mountedonMountedcomponentDidMountuseEffect(fn, [])
更新后updatedonUpdatedcomponentDidUpdateuseEffect(fn, [deps])
卸载beforeDestroy/destroyedonBeforeUnmount/onUnmountedcomponentWillUnmountuseEffect return cleanup
错误捕获errorCapturedonErrorCapturedcomponentDidCatchErrorBoundary 组件

关键差异

  • Vue 自动优化子组件渲染(依赖收集),React 需手动 shouldComponentUpdate / PureComponent / React.memo
  • 两者都符合洋葱模型:父→子创建,子→父挂载

四、Composition API vs React Hook

特性Composition APIReact Hook
调用次数setup 只执行一次每次渲染都重新调用
调用顺序无限制,可在条件/循环中使用必须顶层调用
依赖收集响应式系统自动收集需手动声明依赖数组
GC 压力较小较大(每次渲染创建新闭包)

五、Vue → React 常用写法对照

组件传值

jsx
// Vue:<Child :msg="msg" @update="handleUpdate" />
// React
<Child msg={msg} onUpdate={handleUpdate} />
function Child({ msg, onUpdate }) {
  return <button onClick={() => onUpdate('new')}>{msg}</button>
}

获取 DOM

js
// Vue:const inputRef = ref(null)  // template: ref="inputRef"
// React
const inputRef = useRef(null)  // <input ref={inputRef} />
inputRef.current?.focus()

列表渲染

jsx
// Vue:<div v-for="item in list" :key="item.id">{{ item.name }}</div>
// React
{list.map(item => <div key={item.id}>{item.name}</div>)}

计算属性

js
// Vue:const fullName = computed(() => firstName + ' ' + lastName)
// React
const fullName = useMemo(() => firstName + ' ' + lastName, [firstName, lastName])

监听器

js
// Vue:watch(count, (newVal) => { console.log(newVal) })
// React
useEffect(() => { console.log(count) }, [count])
// 不传第二参数 → 每次渲染执行;传 [] → 仅挂载时执行一次

六、React forwardRef + useImperativeHandle

子组件暴露方法给父组件(类似 Vue 的 defineExpose + ref):

jsx
// 子组件
const Scroll = forwardRef((props, ref) => {
  const bScroll = useRef(null);
  useImperativeHandle(ref, () => ({
    refresh() { bScroll.current?.refresh() },
    scrollTo(x, y) { bScroll.current?.scrollTo(x, y) }
  }));
  return <div>...</div>;
});

// 父组件
const scrollRef = useRef(null);
<Scroll ref={scrollRef} />
scrollRef.current.refresh();  // 调用子组件方法

七、React Hooks 项目编码规范

  • 全面使用函数组件 + Hooks,不再用 class 组件
  • 组件内部状态用 Hooks,业务数据统一放 Redux
  • AJAX 请求和数据处理放在 actionCreator 中(redux-thunk 处理异步)
  • useEffect 统一放在组件顶部,紧跟 props 解构之后
  • mapDispatchToProps 返回的函数命名 xxxDispatch,避免与 action 名冲突
  • 返回 JSX 的函数统一放在组件最后面

八、为什么 React 需要合成事件

  • 兼容性考虑,抹平不同浏览器事件对象差异
  • 避免垃圾回收

相关