生命周期
各阶段调用顺序
// 1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
// 1. constructor()
// 2. getDerivedStateFromProps
// 3. render()
// 4. componentDidMount() =====> 常用
// 一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
// 2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
// 当组件有个新属性传过来,或者state改变时,或调用forceUpdate()强制刷新组件时,会导致组件的更新,更新时
// 1. getDerivedStateFromProps
// 2. shouldComponentUpdate()
// 3. render()
// 4. getSnapshotBeforeUpdate
// 5. componentDidUpdate()
// 3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
// 1. componentWillUnmount() =====> 常用
各生命周期解读
1 //构造器
// constructor就是class组件的构造函数
// 初始化内部状态 很少使用
// 唯一可以直接修改state的地方
constructor(props) {
super(props);
this.state = {
history: this.props.history
};
console.log('执行顺序 constructor');
}
2 // 若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromProps
// 意思就是从props中获取state。即从外部的属性去初始化内部的状态
// 当satet需要从props初始化时使用
// 每次render都会调用
// 因为这个生命周期是静态方法,同时要保持它是纯函数,不要产生副作用。
// 在使用此生命周期时,要注意把传入的 prop 值和之前传入的 prop 进行比较(这个 prop 值最好有唯一性,或者使用一个唯一性的 prop 值来专门比较)。
// 不使用 getDerivedStateFromProps,可以改成组件保持完全不可控模式,通过初始值和 key 值来实现 prop 改变 state 的情景。
// 尽量不使用
getDerivedStateFromProps() {
console.log('执行顺序 getDerivedStateFromProps');
}
3 //组件挂载完毕的钩子
// 渲染完成后的生命周期函数,在这个生命周期里我们一般去发起ajax请求,或者处理一些副作用等。
// 只执行一次
componentDidMount() {
console.log('执行顺序 componentDidMount');
PubSub.subscribe('to-search', (name,data) => {
console.log(`订阅到的消息${name}`, data);
});
}
4 //控制组件更新的“阀门”
// 判断组件是否要更新,在这里可以做一些性能上的优化,避免不需要更新的组件更新,
// 浪费浏览器资源。当调用forceUpdate()时会导致组件跳过 shouldComponentUpdate()。
// 决定dom是否要重绘
// 函数参数
// nextProps:更新后的props属性
// nextState:更新后的state状态
// 这个生命周期中,如果返回true代表会触发重新渲染,为false则不会;默认是返回true
// 必须配合不可变值一起使用,不然会有性能问题
// SCU优化并不一定在一开始就要使用,而是在遇到性能问题时,我们才会考虑使用它
shouldComponentUpdate() {
console.log('执行顺序 shouldComponentUpdate');
}
5 //组件将要卸载的钩子 取消订阅 注销定时器等
componentWillUnmount(){
console.log('执行顺序 componentWillUnmount');
}
6 // 唯一必须定义的生命周期函数,因为我们需要通过在render中写jsx或者createElement来描述我们的界面
render() {
console.log('执行顺序 render');
return (<div></div>)
}
7 //在更新之前获取快照
// 获得之前的dom状态
// 在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息(例如,滚动位置)。
// 此生命周期方法的任何返回值将作为参数传递给 componentDidUpdate()
// prevProps 更新前的props属性
// prevState 更新前的state属性
getSnapshotBeforeUpdate() {
console.log('执行顺序 getSnapshotBeforeUpdate');
}
//组件更新完毕的钩子
// 页面需要根据props变化 重新获取数据
componentDidUpdate(preProps,preState,snapshotValue){
console.log('执行顺序 componentDidUpdate', preProps,preState,snapshotValue);
}
使用示例:
getSnapshotBeforeUpdate(prevProps, prevState) {
// 我们是否在 list 中添加新的 items ?
// 捕获滚动位置以便我们稍后调整滚动位置。
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// 如果我们 snapshot 有值,说明我们刚刚添加了新的 items,
// 调整滚动位置使得这些新 items 不会将旧的 items 推出视图。
//(这里的 snapshot 是 getSnapshotBeforeUpdate 的返回值)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
````