第三章 静态组件与动态组件
内容前瞻
本章将深入探讨 静态组件 和 动态组件 的区别与实现方式,涵盖组件的封装、状态管理、生命周期、更新机制以及高阶组件(HOC)等内容。重点包括:
- 静态组件:函数组件的特点与应用场景。
- 动态组件:类组件与 Hooks 组件的生命周期与状态管理。
- 组件更新机制:
setState
的异步批处理与渲染优化。 - 高阶组件:HOC 的应用场景与实现方式。
静态组件与动态组件
1. 静态组件(函数组件)
- 特点:
- 基于函数实现,无法基于内部状态实现视图更新。
- 适用于不需要动态更新、只需渲染一次的场景。
- 渲染过程:
- 初次渲染:从函数作用域中解析
props
(冻结),生成虚拟 DOM(VDOM)并渲染。 - 后续操作:只更新作用域中的数据,不会触发组件内容的重新渲染。
- 初次渲染:从函数作用域中解析
- 动态化:
- 通过 Hooks(如
useState
、useEffect
)实现状态管理与视图更新。 - 父组件传递不同的
props
,子组件会相应更新。
- 通过 Hooks(如
示例:
jsx
function StaticComponent(props) {
return <div>{props.message}</div>;
}
function ParentComponent() {
const [message, setMessage] = React.useState('Hello');
return (
<div>
<StaticComponent message={message} />
<button onClick={() => setMessage('Updated')}>Update</button>
</div>
);
}
2. 动态组件
- 类组件:
- 生命周期:
- 初次渲染:
getDefaultProps
->getInitialState
->componentWillMount
->render
->componentDidMount
。 - 后续更新:
shouldComponentUpdate
->componentWillUpdate
->render
->componentDidUpdate
。
- 初次渲染:
- 状态初始化:
state
自动挂载到实例上,默认为null
。- 通过
setState
更新状态并触发视图更新。
- 强制更新:
forceUpdate
跳过shouldComponentUpdate
,直接触发重新渲染。
- 生命周期:
示例:
jsx
class DynamicComponent extends React.Component {
state = { count: 0 };
handleClick = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.handleClick}>Increment</button>
</div>
);
}
}
- Hooks 组件:
- 通过
useState
、useEffect
等 Hooks 实现状态管理与生命周期。
- 通过
组件更新机制
1. setState
的异步批处理
- React 18:所有
setState
均为异步操作。 - React 16:合成事件与 Hooks 中为异步,
setTimeout
、DOM 事件等为同步。 - 更新逻辑:
shouldComponentUpdate
->componentWillUpdate
-> 更新数据 ->render
->componentDidUpdate
。
- 回调机制:
this.setState(partialState, callback)
:callback
在状态更新后触发,类似于 Vue 的$nextTick
。
示例:
jsx
this.setState({ count: 1 }, () => {
console.log('State updated');
});
2. flushSync
- 作用:立即处理状态更新队列。
- 使用场景:需要同步更新状态的场景。
示例:
jsx
import { flushSync } from 'react-dom';
flushSync(() => {
this.setState({ count: 1 });
});
受控组件与非受控组件
1. 受控组件
- 特点:通过修改数据驱动视图更新。
- 示例:表单输入框的值由
state
控制。
示例:
jsx
function ControlledComponent() {
const [value, setValue] = React.useState('');
return <input value={value} onChange={(e) => setValue(e.target.value)} />;
}
2. 非受控组件
- 特点:通过
ref
获取 DOM 元素,直接操作 DOM。 - 实现方式:
this.refs.xxx
:通过字符串ref
获取 DOM。ref={(dom) => { this.xxx = dom }}
:通过回调函数获取 DOM。React.createRef()
:创建ref
对象,ref.current
获取 DOM。
示例:
jsx
function UncontrolledComponent() {
const inputRef = React.useRef(null);
return <input ref={inputRef} />;
}
高阶组件(HOC)
1. HOC 的应用场景
- 类组件中使用 JSS:通过 HOC 代理样式处理。
- 通用逻辑复用:如权限校验、日志记录等。
2. HOC 的实现
- 高阶函数:内部返回函数的函数,通过闭包实现函数代理。
- 示例:jsx
function withLogger(WrappedComponent) { return function (props) { console.log('Rendered:', WrappedComponent.name); return <WrappedComponent {...props} />; }; } const EnhancedComponent = withLogger(MyComponent);
重难点 & 容易忽视的点
1. PureComponent
- 特点:继承
PureComponent
后,自动实现shouldComponentUpdate
的浅对比。 - 注意:显式使用
shouldComponentUpdate
会导致警告。
2. 事件委托机制
- React 16:事件委托给
document
。 - React 17+:事件委托给
#root
。 - 优势:减少事件绑定数量,提升性能。
3. 合成事件
- 特点:
onXxx
事件通过 React 封装,支持事件委托。 - 传参:事件对象为最后一个参数。
总结
- 静态组件:适用于无需动态更新的场景,通过 Hooks 实现动态化。
- 动态组件:类组件与 Hooks 组件支持状态管理与生命周期。
- 更新机制:
setState
的异步批处理与flushSync
的同步更新。 - HOC:通过高阶函数实现逻辑复用与组件增强。