React 生命周期详解
生命周期的三个阶段
- 装载过程:
Mouth
React组件的第一次渲染DOM的过程, - 更新过程:
Update
组件数据的更新,重新渲染DOM的过程, - 卸载过程:
Unmouth
组件从DOM树种卸载移除的过程。
装载过程
该过程会调用以下函数
-
constructor ()
该函数是可为了初始化state
和绑定this
, -
getInitialState ()
此函数是ES5写法中初始化state
,,在ES6中已经弃用, -
getDefaultProps()
此函数是ES5写法中初始化props
,在ES6中已经弃用, -
componentWillMount ()
该函数是组件挂载之前调用,只执行一次,可在此函数中使用setState
, 该设置的state
可以在第一次渲染中看到, -
render ()
渲染组件,组件中必须要有该函数, -
componentDidMount ()
该函数是组件挂载完成之后调用, 只执行一次,此时已生成真实DOM节点,这里可以使用refs
。可在此函数中调用ajax
或者设置state
, 该设置的state
可以在第一次渲染中看到。
更新过程
当组件或父组件的props
和state
改变时就会触发更新过程
该过程会调用以下函数
-
componentWillReceiveProps (nextProps)
该函数是父组件render
时 会调用此函数,nextProps
是父组件传递给子组件的数据, 不管父子组件有没有数据交换,或者props
有没有更新,此函数都会执行。 -
shouldComponentUpdate (nextProps, nextState)
组件挂载之后在组件更新之前,判断nextProps
或nextState
与props
或state
的数据是否改变,是否需要重新渲染。默认不写此函数时返回true
,重新渲染,返回false
不重新渲染。在大型应用中有些数据的更新并不影响页面的展示,则可以在此函数中做判断,优化渲染效率。 -
componentWillUpdate (nextProps, nextState)
组件更新之前,当shouldComponentUpdate
函数返回true
时会调用此函数。在此函数中不能使用setState
,否则会陷入死循环。 -
render ()
重新渲染DOM -
componentDidUpdate (prevProps, prevState)
组件更新之后,除了初次渲染外,每次的render
都会调用该函数,渲染结束执行的函数可在此函数中调用。在此函数中不能使用setState
,否则会陷入死循环。
卸载过程
当组件从DOM树种移除时会触发卸载过程
在该函数中可以清除在componentDidMount
中设置的监听函数removeEventListener
,或者在此函数中清除一些setTimeOut
、setInterval
React 示例
子组件
import React from 'react'
class TodoList extends React.Component {
constructor(props, context) {
super(props)
this.state = {
// 初始化state
mount: false
}
}
componentWillMount() {
// 组件挂载之前
console.log('组件挂载之前')
}
componentDidMount() {
// 组件挂载之后
console.log('组件挂载之后')
this.setState({
mount: true
})
}
componentWillReceiveProps(nextProps) {
// 父组件重新渲染时调用
console.log('父组件重新渲染时调用')
}
shouldComponentUpdate(nextProps, nextState) {
// 组件挂载之后数据更新之后
console.log('组件挂载之前,数据更新之后');
// 默认情况下是返回true
return true;
}
componentWillUpdate(nextProps, nextState) {
// 数据重新渲染之前
console.log('数据重新渲染之前');
}
componentDidUpdate(prevProps, prevState) {
// 数据重新渲染之后
console.log('数据重新渲染之后');
}
componentWillUnmount() {
// 组件卸载
console.log('组件卸载');
}
render() {
// 渲染函数 每个组件必须要有
console.log('render');
return (
<div>
render
</div>
)
}
};
export default TodoList;
父组件
import React from 'react'
import TodoList from './components/todoList/index'
export default class App extends React.Component {
constructor(props) {
super(props)
this.state = {
initDone: false
}
}
componentDidMount() {
this.setState({
initDone: true
})
}
render () {
return (
<div>
<TodoList />
</div>
)
}
}
export default App;
渲染到HTML
import { render } from "react-dom"
import App from './App'
render(
<App/>,
document.getElementById('root')
)
控制台输出结果
组件挂载之前
render
组件挂载之后
父组件重新渲染时调用
组件挂载之前,数据更新之后
数据重新渲染之前
render
数据重新渲染之后
后续会做一个官方的经典例子TODOLIST