项目概况

React语法学习

2026-01-296 min read前端技术
react

认识 React 的设计理念

以函数为中心,声明式 UI,组件树结构,单向数据流

与 Vue 对比:Vue 更“魔法”(响应式追踪),React 更“显式”

场景对比

依赖收集(Vue 的响应式 vs React 的 state)

vue

text
1import { ref, reactive, computed } from 'vue' 2 3const count = ref(0) 4const state = reactive({ name: 'Alice' }) 5const double = computed(() => count.value * 2) 6

react

text
1import { useState, useMemo } from 'react' 2 3function Counter() { 4 const [count, setCount] = useState(0) 5 6 // 类似 computed 7 const double = useMemo(() => count * 2, [count]) 8 9 return ( 10 <div> 11 <p>{count}</p> 12 <p>{double}</p> 13 <button onClick={() => setCount(count + 1)}>增加</button> 14 </div> 15 ) 16} 17

父组件触发子组件

vue

vue
1<Child ref="childRef" /> 2<script setup> 3const childRef = ref(null) 4function triggerChild() { 5 childRef.value.sayHi() 6} 7</script> 8

react

react
1import { forwardRef, useImperativeHandle, useRef } from 'react' 2 3const Child = forwardRef((props, ref) => { 4 useImperativeHandle(ref, () => ({ 5 sayHi: () => alert('Hi from Child!') 6 })) 7 return <div>Child Component</div> 8}) 9 10function Parent() { 11 const childRef = useRef(null) 12 return ( 13 <div> 14 <Child ref={childRef} /> 15 <button onClick={() => childRef.current.sayHi()}>触发子组件</button> 16 </div> 17 ) 18} 19

子组件触发父组件事件(事件向上传递)

vue

vue
1<Child @custom-event="handleEvent" /> 2 3// Child 4emit('custom-event', data) 5

react

react
1function Child({ onCustomEvent }) { 2 return <button onClick={() => onCustomEvent('Hello')}>触发父组件</button> 3} 4 5function Parent() { 6 function handleEvent(data) { 7 alert(data) 8 } 9 return <Child onCustomEvent={handleEvent} /> 10}

watch(监听变化)

vue

vue
1watch(() => state.name, (newVal, oldVal) => { ... }) 2

react

react
1import { useEffect, useState } from 'react' 2 3function Demo() { 4 const [name, setName] = useState('Alice') 5 6 useEffect(() => { 7 console.log('name 改变了:', name) 8 }, [name]) // 依赖数组决定监听谁 9 10 return <input value={name} onChange={e => setName(e.target.value)} /> 11} 12

样式定义

vue

vue
1<template> 2 <div :class="{ active: isActive }" :style="{ color: color }">Text</div> 3</template> 4<script setup> 5const isActive = ref(true) 6const color = ref('red') 7</script>

react

react
1function Demo() { 2 const [isActive, setIsActive] = useState(true) 3 const color = 'red' 4 5 return ( 6 <div 7 className={isActive ? 'active' : ''} 8 style={{ color: color }} 9 > 10 Text 11 </div> 12 ) 13}

上下文

vue

vue
1<script setup> 2import { provide, inject } from 'vue' 3 4const theme = 'dark' 5provide('theme', theme) 6</script> 7 8<!-- 子组件 --> 9<script setup> 10const theme = inject('theme') 11console.log(theme) // 'dark' 12</script> 13

react

  • createContext
  • useContext
AlgorithmContext.ts
1import {createContext} from 'react'; 2 3interface ThemeContextType { 4 dark: boolean; 5 switchTheme: () => void; 6} 7 8export const AlgorithmContext = createContext<ThemeContextType>({ 9 dark: false, 10 switchTheme: () => {}, 11});
main.tsx
1export const RootApp = () => { 2 // 用 state 管理主题 3 const {defaultAlgorithm, darkAlgorithm} = theme; 4 const [algorithm, setAlgorithm] = useState(() => defaultAlgorithm); 5 6 const [dark, setDark] = useState(false) 7 const switchTheme = () => { 8 if (dark) { 9 setDark(false) 10 setAlgorithm(() => defaultAlgorithm); 11 } else { 12 setDark(true) 13 setAlgorithm(() => darkAlgorithm); 14 } 15 }; 16 17 return ( 18 <AlgorithmContext.Provider value={{dark, switchTheme}}> 19 <ConfigProvider theme={{ 20 algorithm 21 }}> 22 <FuseChatApp/> 23 </ConfigProvider> 24 </AlgorithmContext.Provider> 25 ) 26}
ChatHeader.txs
1export default function ChatHeader() { 2 const {dark, switchTheme} = useContext(AlgorithmContext); 3 4 return ( 5 <div className="flex items-center justify-end gap-2 px-10"> 6 <Button 7 shape="circle" 8 icon={<CheckSquareOutlined/>} 9 /> 10 <Button 11 shape="circle" 12 onClick={switchTheme} 13 icon={ 14 dark ? ( 15 <MoonOutlined/> 16 ) : ( 17 <SunOutlined/> 18 ) 19 } 20 /> 21 <Button shape="circle" 22 icon={<SettingOutlined/>} 23 /> 24 </div> 25 ); 26}

📚 与 Vue 对比梳理(便于理解)

特性VueReact
模板语法模板字符串JSX(更灵活的 JS)
数据响应式自动收集依赖显式设置 useStateuseEffect
事件绑定@click="fn"onClick={fn}
组件通信props / emitprops / 回调函数
生命周期created, mounteduseEffect

useState

在 vue 中回自动收集依赖,但是在 react 中是没有的,要使用 useState

text
1// 第一个参数是数据,第二个是赋值 2const [count, setCount] = useState(0);

useMemo

useMemo 用来 缓存计算结果,避免不必要的重复计算。

就像 Vue 中的 computed 属性,用于缓存函数返回值。

🧩 对比:Vue computed vs React useMemo

特性Vue computedReact useMemo
是否懒计算✅ 是✅ 是
依赖变了才更新
适用对象模板绑定的值任何计算(变量、函数)

useEffect

🧪 一句话解释 useEffect

useEffect(fn, deps) 的意思是:当组件渲染后,执行 fn;当 deps 变化时,再次执行。

在 Vue 中你有 mounted()、watch()、beforeDestroy() 这些生命周期方法。而 React 函数组件默认没有生命周期 —— 所以就用 useEffect() 来统一处理这些副作用逻辑。

写法含义类似 Vue 生命周期
useEffect(() => {...})每次渲染后都执行updated
useEffect(() => {...}, [])仅首次执行一次mounted
useEffect(() => {...}, [a, b])a 或 b 变化时执行watch
return () => {...}组件卸载前执行,做清理操作beforeDestroy

父子组件

React 中数据是“单向流动”的(单向数据流):父组件可以通过 props 把数据传给子组件,但 子组件不能直接修改父组件的数据。

但我们可以通过一种方式让子组件“修改”父组件的值:让父组件把修改函数也传下去,子组件调用这个函数来“通知”父组件修改。

text
1function Child({ count, onChange }) { 2 return ( 3 <div> 4 <p>子组件收到的 count:{count}</p> 5 <button onClick={() => onChange(count + 1)}>+1</button> 6 <button onClick={() => onChange(0)}>重置</button> 7 </div> 8 ); 9} 10 11import { useState } from 'react'; 12import Child from './Child'; 13 14function Parent() { 15 const [count, setCount] = useState(0); 16 17 const handleChange = (newCount) => { 18 setCount(newCount); 19 }; 20 21 return ( 22 <div> 23 <h2>父组件 Count:{count}</h2> 24 <Child count={count} onChange={handleChange} /> 25 </div> 26 ); 27} 28

Provider

Provider 是 React 中 Context 上下文机制 的一部分,用于让组件树中的任何子组件都能访问到某个值,不用一层层通过 props 传递。

比如:

  • 全局用户信息
  • 多语言(i18n)
  • 主题设置(light/dark)
  • 登录状态
  • 全局弹窗控制
  • 跨页面共享状态(不用 redux)

1️⃣ 创建上下文

text
1import { createContext } from 'react'; 2 3export const UserContext = createContext(null); 4

2️⃣ 提供值(在最外层包一层 Provider)

text
1import { useState } from 'react'; 2import { UserContext } from './UserContext'; 3import Profile from './Profile'; 4 5function App() { 6 const [user, setUser] = useState({ name: '小明', age: 25 }); 7 8 return ( 9 <UserContext.Provider value={user}> 10 <Profile /> 11 </UserContext.Provider> 12 ); 13} 14

3️⃣ 在任意子组件中使用 useContext 获取值

text
1import { useContext } from 'react'; 2import { UserContext } from './UserContext'; 3 4function Profile() { 5 const user = useContext(UserContext); 6 return <h2>用户名是:{user.name}</h2>; 7} 8

对比 Vue

功能Vue 写法React 写法
提供全局值provide('xxx', 值)<MyContext.Provider value={值}>
注入全局值inject('xxx')useContext(MyContext)
全局状态管理推荐vuex / piniacontext / redux / zustand

useTransition

useTransition 是 React 的并发特性之一,主要用于控制「非紧急更新」,让 UI 更加流畅。

js
1import { useTransition, useState } from 'react'; 2 3function App() { 4 const [input, setInput] = useState(''); 5 const [list, setList] = useState([]); 6 const [isPending, startTransition] = useTransition(); 7 8 const handleChange = (e) => { 9 const value = e.target.value; 10 setInput(value); 11 12 // 这里的数据更新被标记为“可延迟” 13 startTransition(() => { 14 const newList = Array.from({ length: 10000 }, (_, i) => `${value} - 项目 ${i}`); 15 setList(newList); 16 }); 17 }; 18 19 return ( 20 <div> 21 <input type="text" value={input} onChange={handleChange} /> 22 {isPending && <p>加载中...</p>} 23 <ul> 24 {list.map((item, i) => ( 25 <li key={i}>{item}</li> 26 ))} 27 </ul> 28 </div> 29 ); 30}