挂载阶段
当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:
-
constructor() 只在实例化时执行一次
-
static getDerivedStateFromProps() 初始化 时执行 数据改变也执行
-
render() 初始化 时执行 数据改变也执行
-
componentDidMount() 挂载完毕执行 一般在这里 进行ajax请求 只执行一次
注意: 下述生命周期方法即将过时,在新代码中应该避免使用它们: UNSAFE_componentWillMount()
- 关于挂载阶段的详情讲解
constructor()
此函数有两个作用 :1.管理应用程序业务逻辑所用到的 数据 2.改变自定义函数的this指向
只能在构造函数中直接为 this.state
赋值。如需在其他方法中赋值,你应使用 this.setState()
替代。
constructor(props) {
super(props);
// 不要在这里调用 this.setState()
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}
static getDerivedStateFromProps()
static getDerivedStateFromProps() 会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
一般当我们需要对其它组件传递过来的数据 进行操作或改变时 使用 static getDerivedStateFromProps()
import React, { Component } from 'react'
import ReactDOM from "react-dom"
export default class One extends Component {
constructor(props){
super(props)
console.log("one-constructor")
this.state = {
a:props.n, //这个状态a称之为派生状态 变成派生状态 才可以在当前文件 对其他组件传递过来的数据进行操作或改变 以this.props 这种形式获取数据 是不可以操作的 会报错
prevProps:props
}
}
//从属性里面获取派生状态 初始化的时候执行,外部传入的props改变的,this.setState()
static getDerivedStateFromProps(props, state){
const prevProps = state.prevProps;
const controlledValue = prevProps.n !== props.n ? props.n : state.a; //判断是外部传入的属性值改变 还是本文件操作派生状态改变
return {
prevProps:props,
a:controlledValue
}
}
}
更新阶段
当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:
- static getDerivedStateFromProps()
- shouldComponentUpdate() //此函数返回true时才会执行reder函数
- render()
- getSnapshotBeforeUpdate() //在更新成真实dom之前执行
- componentDidUpdate() //在更新成真实dom之后执行
注意:
下述方法即将过时,在新代码中应该避免使用它们:
UNSAFE_componentWillUpdate()
UNSAFE_componentWillReceiveProps()
- 关于更新阶段的详情讲解
shouldComponentUpdate() 发生在render函数之前 可以在挂载之前 做一些判断
来决定是否 执行render函数 此函数返回true得时候才会执行render函数
shouldComponentUpdate(nextProps, nextState){
if(this.props.flag !== nextProps.flag){ //之前的属性值与最新的属性值如果不一样的话才会返回true
return true //返回true才会执行render函数
}
return false
}
PureComponent代表纯组件,纯组件内部是不能再去复写shouldComponentUpdate这个钩子函数了
内部进行浅比较(进行值比较或者内部地址的比较),进行性能的优化
注意:如果是值比较的话,外部传入的属性与内部的属性不一样的话,才会进行render更新操作
如果是引用地址比较的话,例如数组,之前的属性数组的地址与更改后的新的数组的地址一致,那么就不会进行render的更新操作
// 使用 PureComponent 纯组件来做性能优化
import React, { Component,PureComponent } from 'react'
export default class index extends Component {
constructor(){
super()
this.state = {
isShow:10,
arr:[1,2]
}
}
render() {
console.log("two-render....")
let {item,change,index} = this.props;
return (
<div>
{ <p>{this.state.isShow}</p>
<p><button onClick={()=>this.setState({isShow:20})}>切换isShow</button></p> }
{<p>{this.state.arr}</p>
<p><button onClick={()=>{
var newArr = [...this.state.arr,3] //因为引用值得地址一致 所以要在创建一个新数组 地址不同 才会执行render函数
this.setState({
arr:newArr
})
}}>切换isShow</button></p> }
</div>
)
}
}
- 性能提升
所谓的性能提升就是说白了,就是在某些场景下可以优化react的render的渲染次数。
1.在普通组件里面可以使用shouldComponentUpdate钩子函数提升react性能。 (nextProps,nextState)
在内部可以判断组件外部接受的最新属性与之前的属性是否一致,从而约束render刷新的时机。
只要结果返回true,render就会立马执行渲染更新,返回false就代表render不会执行。
2.可以使用PureComponent来优化性能。内部机制是通过浅比较去实现的。
3.对于无状态组件的话,使用 React.memo(组件) 来进行性能提升
卸载阶段
当组件从 DOM 中移除时会调用如下方法:
componentWillUnmount()
错误处理
当渲染过程,生命周期,或子组件的构造函数中抛出错误时,会调用如下方法:
-
static getDerivedStateFromError()
-
componentDidCatch()
forceUpdate() 强制更新数据
vue中也有强制更新的方法 this. f o r c e U p d a t e ( ) 和 t h i s . forceUpdate() 和 this. forceUpdate()和this.set()
当数据改变视图没有更新的时候 可以使用强制更新
import React, { Component } from 'react'
export default class index extends Component {
constructor(){
super()
this.state = {
a:10
}
this.b = 100
}
componentDidMount(){
// this.state.a = 20;
// this.forceUpdate() //强制更新
// this.setState({
// a:20
// })
//将一个既不是属性也不是状态的数据更改
this.b = 10000000
this.forceUpdate() //强制更新
}
render() {
return (
<div>
{this.state.a}
<p>{this.b}</p>
</div>
)
}
}