一、旧的生命周期钩子
1、流程图
2、解释
从上图我们不难看出React
16.0
版本之前的钩子的具体执行流程是怎么样的,下面让我们具体解释一下每个钩子的意义,以及在实战中的使用。
注意:这里测试使用钩子时用的是React15.6.2
版本,可自行在bootCDN
官网获取不同版本的React依赖
-
setup props and state
初始化属性和状态
- 在此阶段我们可以对组件的
props
和state
做一些初始化的操作
class Clock extends React.Component { constructor (props) { super(props) // 注意,这里必须传递 props ,否则,下面打印的 this.props 为 undefined console.log(this.state) // { name: 'ralph' } console.log(this.props) // { desc: 'Encounter with React Lifecycle' } } state = { name: 'ralph' } } const props = { desc: 'Encounter with React Lifecycle' } ReactDOM.render(<Clock {...props} />, document.getElementById('box'))
- 在此阶段我们可以对组件的
-
componentWillMount
组件即将渲染到页面上,但是还没渲染
- 由于在这个阶段数据还没有渲染至页面,我们可以对 state 中的数据进行直接修改,不需要通过
setState
api也能正确渲染更新后的数据至页面 - 在这个阶段可以对请求回来的数据进行状态更新
class Clock extends React.Component { constructor (props) { super(props) // 注意,这里必须传递 props ,否则,下面打印的 this.props 为 undefined console.log(this.state) // { name: 'ralph' } console.log(this.props) // { desc: 'Encounter with React Lifecycle' } } componentWillMount () { this.state.name = 'rickey' console.log('componentWillMount') } state = { name: 'ralph' } } const props = { desc: 'Encounter with React Lifecycle' } ReactDOM.render(<Clock {...props} />, document.getElementById('box'))
- 由于在这个阶段数据还没有渲染至页面,我们可以对 state 中的数据进行直接修改,不需要通过
-
render
创建虚拟DOM,更新DOM树,计算diff算法
class Clock extends React.Component { constructor (props) { super(props) // 注意,这里必须传递 props ,否则,下面打印的 this.props 为 undefined console.log(this.state) // { name: 'ralph' } console.log(this.props) // { desc: 'Encounter with React Lifecycle' } } componentWillMount () { this.state.name = 'rickey' console.log('componentWillMount') } render () { const { name } = this.state return ( <div>{ name }</div> ) } state = { name: 'ralph' } } const props = { desc: 'Encounter with React Lifecycle' } ReactDOM.render(<Clock {...props} />, document.getElementById('box'))
-
componentDidMount
组件已经成功渲染至页面上
- 在这个阶段我们可以获取到组件的真实DOM并对它进行DOM操作
class Clock extends React.Component { constructor (props) { super(props) // 注意,这里必须传递 props ,否则,下面打印的 this.props 为 undefined console.log(this.state) // { name: 'ralph' } console.log(this.props) // { desc: 'Encounter with React Lifecycle' } } componentWillMount () { this.state.name = 'rickey' console.log('componentWillMount') } render () { const { name } = this.state // 创建虚拟DOM return ( <div ref='div'>{ name }</div> ) } componentDidMount () { console.log('componentDidMount') console.log(this.refs.div); // 真实DOM --> <div>rickey</div> } state = { name: 'ralph' } } const props = { desc: 'Encounter with React Lifecycle' } ReactDOM.render(<Clock {...props} />, document.getElementById('box'))
-
componentWillReceiveProps
组件中的
props
被更新时调用class Clock extends React.Component { constructor (props) { super(props) // 注意,这里必须传递 props ,否则,下面打印的 this.props 为 undefined console.log(this.state) // { name: 'ralph' } console.log(this.props) // { desc: 'Encounter with React Lifecycle' } } componentWillMount () { this.state.name = 'rickey' console.log('componentWillMount') } render () { const { name } = this.state // 创建虚拟DOM return ( <div> <div ref='div'>{ name }</div> <Child { ...this.state } /> <button onClick={ this.btnclick }>点击修改</button> </div> ) } componentDidMount () { console.log('componentDidMount') console.log(this.refs.div); // 真实DOM --> <div>rickey</div> } btnclick = () => { this.setState({ name: 'Ralph' }) } state = { name: 'ralph' } } class Child extends React.Component { render () { return <div>{ this.props.name }</div> } // nextProps接收到的数值是修改后的 props componentWillReceiveProps (nextProps) { console.log('componentWillReceiveProps', nextProps) // componentWillReceiveProps {name: "ralph"} } } const props = { desc: 'Encounter with React Lifecycle' } ReactDOM.render(<Clock {...props} />, document.getElementById('box'))
-
shouldComponentUpdate
这个钩子将决定此次组件是否需要更新,返回 true 表示更新,false 表示不更新
- 注意:这个钩子函数必须设有返回值,否则会报错
- 在这个函数内部可对数据进行逻辑处理,符合条件则让组件继续更新
class Clock extends React.Component { constructor (props) { super(props) // 注意,这里必须传递 props ,否则,下面打印的 this.props 为 undefined console.log(this.state) // { name: 'ralph' } console.log(this.props) // { desc: 'Encounter with React Lifecycle' } } componentWillMount () { this.state.name = 'rickey' console.log('componentWillMount') } render () { const { name } = this.state // 创建虚拟DOM return ( <div> <div ref='div'>{ name }</div> <Child { ...this.state } /> <button onClick={ this.btnclick }>点击修改</button> </div> ) } componentDidMount () { console.log('componentDidMount') console.log(this.refs.div); // 真实DOM --> <div>rickey</div> } shouldComponentUpdate (...args) { console.log('shouldComponentUpdate', ...args);// 'shouldComponentUpdate' nextprops nextstate nextcontext return true; } btnclick = () => { this.setState({ name: 'Ralph' }) } state = { name: 'ralph' } } class Child extends React.Component { render () { return <div>{ this.props.name }</div> } // nextProps接收到的数值是修改后的 props componentWillReceiveProps (nextProps) { console.log('componentWillReceiveProps', nextProps) // componentWillReceiveProps nextprops nextcontext } } const props = { desc: 'Encounter with React Lifecycle' } ReactDOM.render(<Clock {...props} />, document.getElementById('box'))
-
componentWillUpdate
组件即将更新,但是还没有更新
class Clock extends React.Component { constructor (props) { super(props) // 注意,这里必须传递 props ,否则,下面打印的 this.props 为 undefined console.log(this.state) // { name: 'ralph' } console.log(this.props) // { desc: 'Encounter with React Lifecycle' } } componentWillMount () { this.state.name = 'rickey' console.log('componentWillMount') } render () { const { name } = this.state // 创建虚拟DOM return ( <div> <div ref='div'>{ name }</div> <Child { ...this.state } /> <button onClick={ this.btnclick }>点击修改</button> </div> ) } componentDidMount () { console.log('componentDidMount') console.log(this.refs.div); // 真实DOM --> <div>rickey</div> } shouldComponentUpdate (...args) { console.log('shouldComponentUpdate', ...args); // 'shouldComponentUpdate' nextprops nextstate nextcontext return true; } componentWillUpdate (...args) { console.log('componentWillUpdate', ...args); // 'componentWillUpdate' nextprops nextstate nextcontext } btnclick = () => { this.setState({ name: 'Ralph' }) } state = { name: 'ralph' } } class Child extends React.Component { render () { this.state = this.props return <div>{ this.props.name }</div> } // nextProps接收到的数值是修改后的 props componentWillReceiveProps (nextProps) { console.log('componentWillReceiveProps', nextProps) // componentWillReceiveProps {name: "ralph"} } } const props = { desc: 'Encounter with React Lifecycle' } ReactDOM.render(<Clock {...props} />, document.getElementById('box'))
-
componentDidUpdate
组件已经完成了更新
class Clock extends React.Component { constructor (props) { super(props) // 注意,这里必须传递 props ,否则,下面打印的 this.props 为 undefined console.log(this.state) // { name: 'ralph' } console.log(this.props) // { desc: 'Encounter with React Lifecycle' } } componentWillMount () { this.state.name = 'rickey' console.log('componentWillMount') } render () { const { name } = this.state // 创建虚拟DOM return ( <div> <div ref='div'>{ name }</div> <Child { ...this.state } /> <button onClick={ this.btnclick }>点击修改</button> </div> ) } componentDidMount () { console.log('componentDidMount') console.log(this.refs.div); // 真实DOM --> <div>rickey</div> } shouldComponentUpdate (...args) { console.log('shouldComponentUpdate', ...args); // 'shouldComponentUpdate' nextprops nextstate nextcontext return true; } componentWillUpdate (...args) { console.log('componentWillUpdate', ...args); // 'componentWillUpdate' nextprops nextstate nextcontext } componentDidUpdate (...args) { console.log('componentDidUpdate', ...args); // 'componentWillUpdate' nextprops nextstate nextcontext } btnclick = () => { this.setState({ name: 'Ralph' }) } state = { name: 'ralph' } } class Child extends React.Component { render () { this.state = this.props return <div>{ this.props.name }</div> } // nextProps接收到的数值是修改后的 props componentWillReceiveProps (nextProps) { console.log('componentWillReceiveProps', nextProps) // componentWillReceiveProps {name: "ralph"} } } const props = { desc: 'Encounter with React Lifecycle' } ReactDOM.render(<Clock {...props} />, document.getElementById('box'))
-
componentWillUnmount
组件即将被卸载
- 本文中通过使用
ReactDOM
模块中的unmountComponentAtNode
API卸载一个组件 - 在此处我们可以对一些连接进行释放,提高性能
constructor (props) { super(props) // 注意,这里必须传递 props ,否则,下面打印的 this.props 为 undefined console.log(this.state) // { name: 'ralph' } console.log(this.props) // { desc: 'Encounter with React Lifecycle' } } componentWillMount () { this.state.name = 'rickey' console.log('componentWillMount') } render () { const { name } = this.state // 创建虚拟DOM return ( <div> <div ref='div'>{ name }</div> <Child { ...this.state } /> <button onClick={ this.btnclick }>点击修改</button> <button onClick={ this.unmountCurrentComponent }>点击卸载组件</button> </div> ) } componentDidMount () { console.log('componentDidMount') console.log(this.refs.div); // 真实DOM --> <div>rickey</div> } shouldComponentUpdate (...args) { console.log('shouldComponentUpdate', ...args); // 'shouldComponentUpdate' nextprops nextstate nextcontext return true; } componentWillUpdate (...args) { console.log('componentWillUpdate', ...args); // 'componentWillUpdate' nextprops nextstate nextcontext } componentDidUpdate (...args) { console.log('componentDidUpdate', ...args); // 'componentWillUpdate' nextprops nextstate nextcontext } componentWillUnmount () { console.log('componentWillUnmount'); } btnclick = () => { this.setState({ name: 'Ralph' }) } unmountCurrentComponent = () => { ReactDOM.unmountComponentAtNode(document.getElementById('box')) } state = { name: 'ralph' } } class Child extends React.Component { render () { this.state = this.props return <div>{ this.props.name }</div> } // nextProps接收到的数值是修改后的 props componentWillReceiveProps (nextProps) { console.log('componentWillReceiveProps', nextProps) // componentWillReceiveProps {name: "ralph"} } } const props = { desc: 'Encounter with React Lifecycle' } ReactDOM.render(<Clock {...props} />, document.getElementById('box')) const props = { desc: 'Encounter with React Lifecycle' } ReactDOM.render(<Clock {...props} />, document.getElementById('box'))
- 本文中通过使用
二、新的生命周期钩子
1、流程图
2、解释
新版本生命周期更新详情
- 被移除的钩子
- componentWillMount
- componentWillUpdate
- 被重名的钩子
UNSAFE_
componentWillReceiveProps
-
getDerivedStateFromProps
在此阶段无论是创建阶段还是更新阶段都会触发此函数的调用,这个方法是一个派生方法,所以需要通过
static
修饰。此函数应返回一个对象
来更新 state,如果返回null
则不更新任何内容。
作用:getDerivedStateFromProps
的存在只有一个目的:让组件在 props 变化时更新 state
-
getSnapshotBeforeUpdate
此方法需要返回一个
snapshot
值或者null
这个函数会在每次更新之前调用,返回值将作为componentDidUpdate
的第三个参数返回。
此方法可用于以特殊方式处理滚动位置的聊天线程中。