React 组件的渲染过程大致分为几个步骤:
-
初始化阶段:
- 当组件被引入到React应用中时,首先会进行初始化。初始化的过程包括设置组件的默认属性(
defaultProps
),以及组件的初始状态(state
)。
- 当组件被引入到React应用中时,首先会进行初始化。初始化的过程包括设置组件的默认属性(
-
挂载阶段(Mounting):
- constructor:如果组件是一个类组件,会首先调用构造函数,进行一些如状态的初始化等操作。
- getDerivedStateFromProps(可选):在组件实例化后和重新渲染之前调用,可以用来根据props来更新state。
- render:该方法是组件渲染的核心。它会对当前组件的
props
与state
进行分析,并返回一个React元素(通常是虚拟DOM节点),这个返回的元素可以是原生DOM的表现、也可以是其它组件的集合。值得注意的是,render
方法是纯函数,不应该包含任何会改变组件状态的代码。 - componentDidMount:组件挂载完成后调用。这是执行副作用操作的理想位置,如发起网络请求、设置定时器等操作。
-
更新阶段(Updating): 组件的props或state发生变化时,组件会重新渲染,其过程如下:
- getDerivedStateFromProps(可选):如上所述,这个方法用在props发生变化时根据新的props来更新state。
- shouldComponentUpdate(可选):通过返回值决定组件是否应当进行更新。如果返回false,则不会调用render方法,也不会进行后面的更新过程。
- render:重新执行render函数,与初始化阶段的render相同。
- getSnapshotBeforeUpdate(可选):在DOM更新前被调用,用于捕获更新前的DOM状态。
- componentDidUpdate:组件更新完成后被调用,可以执行例如更新DOM的操作。
-
卸载阶段(Unmounting):
- componentWillUnmount:组件将要被卸载之前调用,进行必要的清理工作,如清除定时器、取消网络请求等。
在这个过程中,React还会对组件树进行优化,使用虚拟DOM和Diff算法来减少实际DOM操作的次数,从而提高性能。
例子:
假设我们有一个简单的计数器组件 Counter
,它有一个按钮用来增加计数,计数的值保存在状态 count
中。当用户点击按钮时,组件的state会更新,触发更新流程:
jsxclass Counter extends React.Component { constructor(props) { super(props); this.state = { count: 0 }; } componentDidMount() { console.log('Counter: componentDidMount'); } componentDidUpdate() { console.log('Counter: componentDidUpdate'); } componentWillUnmount() { console.log('Counter: componentWillUnmount'); } increment = () => { this.setState(state => ({ count: state.count + 1 })); }; render() { return ( <div> <p>Count: {this.state.count}</p> <button onClick={this.increment}>Increment</button> </div> ); } }
在这个例子中:
- 当
Counter
首次加载进React树时,constructor、render 和 componentDidMount会依次被调用。 - 当用户点击按钮时,
increment
方法通过setState
更新组件的state,触发组件的更新流程。 - 因为state发生了变化,shouldComponentUpdate(如果定义了的话)和render方法会被调用,接着如果有必要,getSnapshotBeforeUpdate和componentDidUpdate也会被调用。
- 当组件要被移除时,componentWillUnmount会被调用。