React生命周期:挂载,更新,卸载,这篇文章会详细介绍各个生命周期中的钩子函数以及作用
(1)挂载阶段
class App extends React.Component {
//1:设置默认属性
static defaultProps = {
n: 1,
}
//2:初始化状态
//创建组件实例,本质是创建一个新的对象
//把方法绑定到this上
constructor(props) {
//super本质:this.props = props,在此之后才有this实例
console.log('constructor');
super(props)
this.state = {m:0}
//绑定完this后生成一个新对象赋值给当前实例
this.go2 = this.go2.bind(this)
}
//go1是对象,直接绑定到组件实例上
go1 = {a:1}
//go2是方法,绑定到组件原型对象上
go2(){
console.log(this);
}
//3:第一次组件渲染之前执行,只会执行一次
//此时能够获取当前组件实例的state和props
//该钩子函数常用在服务器端渲染
//现已被UNSAFE_componentWillMount替代
componentWillMount() {
console.log('componentWillMount');
//会报警告,推荐使用setState修改值
this.state = {m:1}
//可以修改值但是不会触发render,因为这时还没有render
this.setState({m:1})
//可以触发render,render不会阻塞渲染
//不适合做网络请求,时机不确定,会出现二次渲染
setTimeout(()=>{
this.setState({m:1})
},5000)
}
//4:渲染函数,纯函数
//第一次挂载时,数据更新时会触发
//解析jsx 虚拟DOM=>(第一次直接渲染,更新时使用diff算法)=>真实dom=>视图
//类组件必须写该方法
//使用setState会导致死循环,内存溢出
render() {
console.log('render');
return(
<div>
count : {this.state.m}
{/*绑定时先去原型对象上寻找go2,然后把这个go2绑定到组件实例上*/}
<button onClick={this.go2.bind(this)}></button>
</div>
)
}
//5:第一次渲染完毕触发
//网络请求,事件监听,操作dom,定时器都写在这里
componentDidMount(){
}
}
ReactDOM.render(<App />, document.getElementById('app'))
在声明书属性使需要注意
constructor外面的属性会按顺序陆续添加到constructor里面初始化
排在前面的属性使用到后面的属性时,后面的属性会undefined
解决方案:
1:调整顺序
2:将排在前面且需要调用后面的属性放到constructor里,
因为初始化顺序是先初始化constructor外的属性,再初始化constructor里面的属性
(2)更新阶段
class App extends React.Component {
constructor(props) {
console.log('constructor');
super(props)
this.state = {m:0}
}
UNSAFE_componentWillMount(){
console.log('UNSAFE_componentWillMount');
}
// 接收参数前的钩子函数
//父组件渲染,子组件也渲染,子组件从该钩子函数开始
//当子组件的state对props有依赖时会用到
//使用setState不会触发render
// componentWillReceiveProps(nextProps){
// console.log('componentWillReceiveProps');
// }
UNSAFE_componentWillReceiveProps(nextProps){
console.log('UNSAFE_componentWillReceiveProps');
console.log(nextProps);
this.setState({
m:2
})
}
//1:判断是否更新
//返回true调用render,返回false不调用
//根据props和state判断是否重新渲染
//状态比较:this.state和nextState(变化后的值)
//props比较:this.props和nextProps
shouldComponentUpdate(nextProps,nextState){
console.log('shouldComponentUpdate');
if(this.state.m === nextState.m && this.props.a === nextProps.a ){
return false
}
return true
}
//2:更新前触发钩子函数
//现已经改名为UNSAFE_componentWillUpdate
// componentWillUpdate(){
// }
UNSAFE_componentWillUpdate(){
console.log('UNSAFE_componentWillUpdate');
}
//3:更新渲染
render() {
console.log('render');
return(
<div>
count:{this.state.m}
count:{this.props.a}
<button onClick={
//箭头函数没有this,会找到外围的this,也就是render的this,指向组件实例
()=>{
this.setState({
m:1
})
}}>更新</button>
</div>
)
}
//4:更新完毕触发
componentDidUpdate(){
console.log('componentDidUpdate');
}
//5:第一次渲染完毕触发
componentDidMount(){
console.log('componentDidMount');
}
}
class AppFather extends React.Component {
constructor(props){
console.log('father-constructor');
super(props)
this.state = {a:10}
}
UNSAFE_componentWillMount(){
console.log('father-UNSAFE_componentWillMount');
}
shouldComponentUpdate(nextProps,nextState){
console.log('father-shouldComponentUpdate');
return true
}
UNSAFE_componentWillUpdate(){
console.log('father-UNSAFE_componentWillUpdate');
}
render(){
console.log('father-render');
return(
<div>
{/*给子组件传值*/}
<App a= {this.state.a} />
<button onClick={
()=>{
this.setState({
a:12
})
}}>更新父类</button>
</div>
)
}
componentDidUpdate(){
console.log('father-componentDidUpdate');
}
componentDidMount(){
console.log('father-componentDidMount');
}
}
ReactDOM.render(<AppFather />, document.getElementById('app'))
(3)卸载阶段
class App extends React.Component {
constructor(props) {
console.log('constructor');
super(props)
this.state = {m:0}
}
UNSAFE_componentWillMount(){
console.log('UNSAFE_componentWillMount');
}
UNSAFE_componentWillReceiveProps(nextProps){
console.log('UNSAFE_componentWillReceiveProps');
console.log(nextProps);
this.setState({
m:2
})
}
shouldComponentUpdate(nextProps,nextState){
console.log('shouldComponentUpdate');
if(this.state.m === nextState.m && this.props.a === nextProps.a ){
return false
}
return true
}
UNSAFE_componentWillUpdate(){
console.log('UNSAFE_componentWillUpdate');
}
render() {
console.log('render');
return(
<div>
count:{this.state.m}
count:{this.props.a}
<button onClick={
()=>{
this.setState({
m:1
})
}}>更新</button>
</div>
)
}
componentDidUpdate(){
console.log('componentDidUpdate');
}
componentDidMount(){
console.log('componentDidMount');
}
//组件卸载钩子函数,释放资源
//多用于隐藏显示,页面跳转,手动移除
//想执行父组件卸载钩子,然后陆续递归执行子组件卸载钩子
componentWillUnmount(){
console.log('componentWillUnmount');
}
}
class AppFather extends React.Component {
constructor(props){
console.log('father-constructor');
super(props)
this.state = {a:10}
}
UNSAFE_componentWillMount(){
console.log('father-UNSAFE_componentWillMount');
}
shouldComponentUpdate(nextProps,nextState){
console.log('father-shouldComponentUpdate');
return true
}
UNSAFE_componentWillUpdate(){
console.log('father-UNSAFE_componentWillUpdate');
}
render(){
console.log('father-render');
return(
<div>
<App a= {this.state.a} />
<button onClick={
()=>{
this.setState({
a:12
})
}}>更新父类</button>
<button onClick={
()=>{
ReactDOM.unmountComponentAtNode(document.getElementById('app'))
}}>卸载</button>
</div>
)
}
componentDidUpdate(){
console.log('father-componentDidUpdate');
}
componentDidMount(){
console.log('father-componentDidMount');
}
componentWillUnmount(){
console.log('father-componentWillUnmount');
}
}
ReactDOM.render(<AppFather />, document.getElementById('app'))
(4)高性能组件PureComponent
React.PureComponent和Component很相似,但是PureComponent性能更高;
它会自动检测是否需要更新
也就是自动模拟shouldComponentUpdate这个钩子函数来确保不会重复无效刷新