Appearance
React API 详细文档
本文档详细介绍React的所有API,包括它们的作用、实现原理、区别和使用场景。
目录
- 核心API
- React.createElement()
- React.cloneElement()
- React.createFactory()
- React.isValidElement()
- React.Children
- React.Fragment
- React.StrictMode
- React.Suspense
- React.lazy()
- React.memo()
- React.useState()
- React.useEffect()
- React.useContext()
- React.useReducer()
- React.useCallback()
- React.useMemo()
- React.useRef()
- React.useImperativeHandle()
- React.useLayoutEffect()
- React.useDebugValue()
- 组件API
- DOM API
- 事件API
- Hooks API
- 其他API
核心API
React.createElement()
作用:创建一个React元素。
实现原理:
- 接收三个参数:type(元素类型)、props(属性)、children(子元素)
- 返回一个React元素对象,包含type、props等信息
- 是JSX语法的底层实现
使用场景:
- 当需要动态创建React元素时
- 当不使用JSX语法时
示例:
jsx
const element = React.createElement(
'div',
{ className: 'container' },
'Hello World'
)React.cloneElement()
作用:克隆并返回一个新的React元素,新元素会保留原始元素的props,并可以添加新的props。
实现原理:
- 接收三个参数:element(要克隆的元素)、props(新的属性)、children(新的子元素)
- 合并原始元素的props和新的props
- 返回一个新的React元素
使用场景:
- 当需要基于现有元素创建一个稍有不同的新元素时
- 当需要向子元素传递额外的props时
示例:
jsx
const clonedElement = React.cloneElement(element, { id: 'new-id' })React.createFactory()
作用:创建一个React元素工厂函数。
实现原理:
- 接收一个type参数,返回一个函数
- 调用返回的函数时,会创建并返回一个指定类型的React元素
使用场景:
- 当需要创建多个相同类型的React元素时
- 已被JSX语法替代,现在较少使用
示例:
jsx
const divFactory = React.createFactory('div')
const element = divFactory({ className: 'container' }, 'Hello World')React.isValidElement()
作用:检查一个值是否为有效的React元素。
实现原理:
- 接收一个参数,检查它是否是一个React元素对象
- 判断该对象是否有$$typeof属性且值为Symbol.for('react.element')
使用场景:
- 当需要验证一个值是否为React元素时
- 在处理可能是React元素也可能是其他类型值的情况下
示例:
jsx
const isElement = React.isValidElement(element)React.Children
作用:提供用于处理React子元素的工具方法。
实现原理:
- 包含map、forEach、count、only、toArray等方法
- 处理各种子元素情况,包括单个元素、数组、null、undefined等
使用场景:
- 当需要遍历或操作组件的子元素时
- 当需要处理子元素的各种边缘情况时
示例:
jsx
const childrenArray = React.Children.toArray(this.props.children)React.Fragment
作用:允许将多个元素组合在一起,而不需要额外的DOM节点。
实现原理:
- 是一个特殊的React元素,不会在DOM中渲染
- 可以包含多个子元素
- 可以使用key属性
使用场景:
- 当需要返回多个元素但不想添加额外的DOM节点时
- 当需要在列表中使用key属性时
示例:
jsx
<React.Fragment>
<div>First</div>
<div>Second</div>
</React.Fragment>React.StrictMode
作用:用于在开发模式下检测潜在问题。
实现原理:
- 不渲染任何可见元素
- 在开发模式下,会额外运行一些检查和警告
- 帮助发现不安全的生命周期方法、过时的API等
使用场景:
- 在开发模式下包裹应用或组件,以检测潜在问题
- 不影响生产环境的行为
示例:
jsx
<React.StrictMode>
<App />
</React.StrictMode>React.Suspense
作用:用于处理组件的加载状态。
实现原理:
- 可以包裹懒加载的组件
- 当组件正在加载时,显示fallback属性指定的内容
- 与React.lazy()配合使用
使用场景:
- 当需要懒加载组件时
- 当需要在组件加载过程中显示加载状态时
示例:
jsx
<React.Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</React.Suspense>React.lazy()
作用:用于懒加载组件。
实现原理:
- 接收一个函数,该函数返回一个Promise,Promise解析为一个React组件
- 当组件首次渲染时,会加载该组件
- 与React.Suspense配合使用
使用场景:
- 当需要按需加载组件以减少初始加载时间时
- 当组件较大且不总是需要时
示例:
jsx
const LazyComponent = React.lazy(() => import('./LazyComponent'))React.memo()
作用:用于优化函数组件的渲染性能。
实现原理:
- 接收一个函数组件和一个比较函数
- 当组件的props没有变化时,会跳过渲染
- 使用浅比较来比较props
使用场景:
- 当组件的渲染成本较高且props变化不频繁时
- 当组件的props是基本类型且变化较少时
示例:
jsx
const MemoizedComponent = React.memo(MyComponent)组件API
Component 类
作用:React组件的基类,用于创建类组件。
实现原理:
- 提供setState()方法用于更新状态
- 提供生命周期方法
- 管理组件的状态和渲染
使用场景:
- 当需要使用生命周期方法时
- 当组件的状态管理较复杂时
- 当需要访问this关键字时
示例:
jsx
class MyComponent extends React.Component {
render() {
return <div>{this.props.name}</div>
}
}PureComponent 类
作用:Component的子类,用于优化渲染性能。
实现原理:
- 自动实现了shouldComponentUpdate()方法
- 使用浅比较来比较props和state
- 当props和state没有变化时,跳过渲染
使用场景:
- 当组件的props和state是基本类型且变化较少时
- 当组件的渲染成本较高时
- 当不需要自定义shouldComponentUpdate()逻辑时
示例:
jsx
class MyPureComponent extends React.PureComponent {
render() {
return <div>{this.props.name}</div>
}
}DOM API
ReactDOM.render()
作用:将React元素渲染到DOM中。
实现原理:
- 接收三个参数:element(React元素)、container(DOM容器)、callback(回调函数)
- 将React元素转换为DOM元素并插入到容器中
- 当组件更新时,会执行差异比较并只更新变化的部分
使用场景:
- 当需要将React应用渲染到DOM中时
- 当需要在现有DOM中插入React组件时
示例:
jsx
ReactDOM.render(<App />, document.getElementById('root'))ReactDOM.hydrate()
作用:用于服务端渲染的应用,将服务器生成的HTML与客户端React代码进行关联。
实现原理:
- 与render()方法类似,但会保留服务器生成的HTML
- 只添加事件监听器和执行必要的更新
- 提高首屏加载性能
使用场景:
- 当应用使用服务端渲染时
- 当需要将服务器生成的HTML与客户端React代码关联时
示例:
jsx
ReactDOM.hydrate(<App />, document.getElementById('root'))ReactDOM.unmountComponentAtNode()
作用:从DOM中卸载React组件。
实现原理:
- 接收一个DOM容器参数
- 从容器中移除React组件
- 清理组件的事件监听器和状态
使用场景:
- 当需要手动卸载React组件时
- 当组件不再需要时
示例:
jsx
ReactDOM.unmountComponentAtNode(document.getElementById('root'))ReactDOM.createPortal()
作用:将子元素渲染到DOM中的任意位置。
实现原理:
- 接收两个参数:children(子元素)、container(DOM容器)
- 子元素会被渲染到指定的容器中,但仍然是React组件树的一部分
- 事件会正确冒泡到父组件
使用场景:
- 当需要将组件渲染到DOM中的其他位置时
- 当需要创建模态框、弹出菜单等组件时
示例:
jsx
ReactDOM.createPortal(
<div>Portal content</div>,
document.getElementById('portal-container')
)事件API
React合成事件系统
作用:提供跨浏览器一致的事件处理机制。
实现原理:
- 事件委托:将事件监听器添加到document上
- 事件池:重用事件对象以提高性能
- 标准化事件属性和方法
使用场景:
- 当需要处理用户交互事件时
- 当需要跨浏览器兼容的事件处理时
示例:
jsx
function MyComponent() {
const handleClick = e => {
console.log('Clicked')
}
return <button onClick={handleClick}>Click me</button>
}Hooks API
基本Hooks
React.useState()
作用:在函数组件中添加状态。
实现原理:
- 接收一个初始状态值
- 返回一个数组,包含当前状态和更新状态的函数
- 当状态更新时,组件会重新渲染
使用场景:
- 当函数组件需要状态时
- 当需要在组件中保存和更新数据时
示例:
jsx
function MyComponent() {
const [count, setCount] = React.useState(0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
)
}React.useEffect()
作用:在函数组件中执行副作用操作。
实现原理:
- 接收一个回调函数和一个依赖数组
- 当组件挂载、更新或卸载时执行回调函数
- 依赖数组控制回调函数的执行时机
使用场景:
- 当需要在组件挂载后执行操作时
- 当需要处理副作用,如网络请求、订阅等时
- 当需要在组件卸载时清理资源时
示例:
jsx
function MyComponent() {
React.useEffect(() => {
// 执行副作用操作
return () => {
// 清理操作
}
}, [dependencies])
return <div>Component</div>
}React.useContext()
作用:在函数组件中访问Context。
实现原理:
- 接收一个Context对象
- 返回该Context的当前值
- 当Context值变化时,组件会重新渲染
使用场景:
- 当需要在组件树中传递数据,而不需要通过props逐层传递时
- 当多个组件需要访问相同的数据时
示例:
jsx
const ThemeContext = React.createContext('light')
function MyComponent() {
const theme = React.useContext(ThemeContext)
return <div>Current theme: {theme}</div>
}额外Hooks
React.useReducer()
作用:在函数组件中使用reducer来管理状态。
实现原理:
- 接收一个reducer函数和初始状态
- 返回一个数组,包含当前状态和dispatch函数
- 当dispatch一个action时,reducer函数会处理action并返回新的状态
使用场景:
- 当状态管理较复杂时
- 当状态更新依赖于之前的状态时
- 当需要处理多个相关的状态更新时
示例:
jsx
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 }
case 'decrement':
return { count: state.count - 1 }
default:
return state
}
}
function MyComponent() {
const [state, dispatch] = React.useReducer(reducer, { count: 0 })
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
</div>
)
}React.useCallback()
作用:返回一个 memoized 回调函数。
实现原理:
- 接收一个回调函数和一个依赖数组
- 当依赖数组中的值不变时,返回相同的回调函数引用
- 避免不必要的重新渲染
使用场景:
- 当需要将回调函数作为props传递给子组件时
- 当子组件使用React.memo()优化时
- 当回调函数创建成本较高时
示例:
jsx
function MyComponent() {
const handleClick = React.useCallback(() => {
console.log('Clicked')
}, [])
return <ChildComponent onClick={handleClick} />
}React.useMemo()
作用:返回一个 memoized 值。
实现原理:
- 接收一个计算函数和一个依赖数组
- 当依赖数组中的值不变时,返回缓存的值
- 避免不必要的重新计算
使用场景:
- 当需要进行昂贵的计算时
- 当计算结果需要作为props传递给子组件时
- 当计算结果依赖于某些值时
示例:
jsx
function MyComponent({ a, b }) {
const result = React.useMemo(() => {
// 昂贵的计算
return a + b
}, [a, b])
return <div>Result: {result}</div>
}React.useRef()
作用:在函数组件中创建一个可变的ref对象。
实现原理:
- 接收一个初始值
- 返回一个ref对象,包含current属性
- ref对象在组件的整个生命周期中保持不变
- 修改ref.current不会触发组件重新渲染
使用场景:
- 当需要访问DOM元素时
- 当需要在组件之间保存一个可变值,而不需要触发重新渲染时
- 当需要在useEffect中保存一个值时
示例:
jsx
function MyComponent() {
const inputRef = React.useRef(null)
const focusInput = () => {
inputRef.current.focus()
}
return (
<div>
<input ref={inputRef} />
<button onClick={focusInput}>Focus Input</button>
</div>
)
}React.useImperativeHandle()
作用:自定义暴露给父组件的ref方法。
实现原理:
- 接收一个ref对象、一个创建句柄的函数和一个依赖数组
- 允许子组件自定义通过ref暴露给父组件的方法和属性
- 与React.forwardRef()配合使用
使用场景:
- 当父组件需要调用子组件的方法时
- 当需要限制子组件暴露给父组件的内容时
示例:
jsx
const MyComponent = React.forwardRef((props, ref) => {
const inputRef = React.useRef(null)
React.useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus()
}
}))
return <input ref={inputRef} />
})React.useLayoutEffect()
作用:与useEffect类似,但在DOM更新后同步执行。
实现原理:
- 与useEffect的API相同
- 但执行时机不同:useLayoutEffect在DOM更新后同步执行,useEffect在浏览器完成绘制后异步执行
- 适用于需要在DOM更新后立即执行的操作
使用场景:
- 当需要在DOM更新后立即执行操作时
- 当需要测量DOM元素的尺寸或位置时
- 当需要避免布局闪烁时
示例:
jsx
function MyComponent() {
const ref = React.useRef(null)
React.useLayoutEffect(() => {
// 测量DOM元素
console.log(ref.current.offsetHeight)
}, [])
return <div ref={ref}>Component</div>
}React.useDebugValue()
作用:在React DevTools中显示自定义Hook的标签。
实现原理:
- 接收一个值和一个格式化函数
- 在React DevTools中显示该值
- 仅在开发模式下有效
使用场景:
- 当创建自定义Hook时
- 当需要在React DevTools中显示有意义的信息时
示例:
jsx
function useCustomHook() {
const [value, setValue] = React.useState(0)
React.useDebugValue(value > 0 ? 'Positive' : 'Negative')
return [value, setValue]
}其他API
React.version
作用:获取当前React的版本号。
实现原理:
- 是一个字符串,包含当前React的版本号
- 可以用于条件判断或日志记录
使用场景:
- 当需要根据React版本执行不同的代码时
- 当需要在日志中记录React版本时
示例:
jsx
console.log('React version:', React.version)React.isValidElement()
作用:检查一个值是否为有效的React元素。
实现原理:
- 接收一个参数,检查它是否是一个React元素对象
- 判断该对象是否有$$typeof属性且值为Symbol.for('react.element')
使用场景:
- 当需要验证一个值是否为React元素时
- 在处理可能是React元素也可能是其他类型值的情况下
示例:
jsx
const isElement = React.isValidElement(element)React.Children.map()
作用:遍历React子元素并返回一个新的数组。
实现原理:
- 接收children和一个回调函数
- 对每个子元素执行回调函数
- 处理各种子元素情况,包括单个元素、数组、null、undefined等
使用场景:
- 当需要遍历并转换子元素时
- 当需要为每个子元素添加额外的props时
示例:
jsx
const newChildren = React.Children.map(this.props.children, (child, index) => {
return React.cloneElement(child, { key: index })
})React.Children.forEach()
作用:遍历React子元素并执行回调函数。
实现原理:
- 接收children和一个回调函数
- 对每个子元素执行回调函数
- 不返回任何值
使用场景:
- 当需要遍历子元素并执行副作用操作时
- 当不需要返回新的子元素数组时
示例:
jsx
React.Children.forEach(this.props.children, child => {
console.log(child)
})React.Children.count()
作用:计算React子元素的数量。
实现原理:
- 接收children参数
- 返回子元素的数量
- 处理各种子元素情况,包括单个元素、数组、null、undefined等
使用场景:
- 当需要知道子元素的数量时
- 当需要根据子元素数量执行不同的逻辑时
示例:
jsx
const count = React.Children.count(this.props.children)React.Children.only()
作用:验证children是否只有一个子元素,并返回该子元素。
实现原理:
- 接收children参数
- 如果children只有一个子元素,返回该子元素
- 否则,抛出错误
使用场景:
- 当组件只接受一个子元素时
- 当需要确保children只有一个子元素时
示例:
jsx
const onlyChild = React.Children.only(this.props.children)React.Children.toArray()
作用:将React子元素转换为一个数组。
实现原理:
- 接收children参数
- 返回一个包含所有子元素的数组
- 处理各种子元素情况,包括单个元素、数组、null、undefined等
使用场景:
- 当需要将子元素作为数组处理时
- 当需要对排序或过滤子元素时
示例:
jsx
const childrenArray = React.Children.toArray(this.props.children)总结
React提供了丰富的API,用于创建和管理组件、处理状态和副作用、操作DOM等。这些API可以分为核心API、组件API、DOM API、事件API和Hooks API等类别。
API对比
| API类别 | 主要用途 | 特点 |
|---|---|---|
| 核心API | 创建和操作React元素 | 提供基础的React元素创建和操作功能 |
| 组件API | 创建和管理组件 | 提供类组件的基类和优化 |
| DOM API | 操作DOM | 提供将React元素渲染到DOM的功能 |
| 事件API | 处理用户交互 | 提供跨浏览器一致的事件处理机制 |
| Hooks API | 在函数组件中使用状态和副作用 | 提供在函数组件中使用状态和副作用的能力 |
使用建议
优先使用函数组件和Hooks:函数组件和Hooks是React的现代方式,代码更简洁,更易于理解和维护。
合理使用React.memo()、useCallback()和useMemo():这些API可以优化组件的渲染性能,但不要过度使用,以免增加代码复杂性。
使用Context API管理全局状态:当多个组件需要访问相同的数据时,使用Context API可以避免props逐层传递。
使用React.lazy()和React.Suspense实现代码分割:这可以减少初始加载时间,提高应用性能。
遵循React的最佳实践:如使用key属性、避免在render中创建函数、正确处理副作用等。
通过合理使用React的各种API,可以创建高性能、可维护的React应用。