一、React 类组件有哪些常用生命周期钩子?
生命周期钩子: 不管是vue
还是react
, 所谓生命周期钩子,本质就是一个在特定时间和场合要执行的函数。
暴露出一些函数给开发者,如果开发者定义了这些函数,在是生命周期对应的某个阶段,去执行指定的函数,进而实现特定的功能。
二、生命周期钩子的分类。
生命周期钩子函数分为三个阶段:
- 挂载阶段 ,一般是组件的首次渲染,主要包括组件的创建,渲染、挂载。
- 更新阶段, 当组件的状态(响应式数据)发生变化以后,会引起页面的重新渲染。在这个过程中也会涉及一些生命周期钩子。
- 卸载阶段。当不再需要某个组件的时候,将这个组件从页面移除(路由切换,页面切换),框架也会提供对应的生命周期函数,让开发者在里面做一些善尾的工作,比如清除定时器,事件监听等。
react 类组件的生命周期演变:
版本 | 首次挂载阶段 | 更新阶段 | 卸载阶段 |
---|---|---|---|
React16.3以前 | 1. constructor 2. componentWillMount 3. render 4. componentDidMount | 1.componentWillReceiveProps 2. shouldComponentUpdate 3. componentWillUpdate 4. render 5. componentDidUpdate | componentWillUnmoun |
新的生命周期钩子 | 1. construct 2.getDerivedStateFromProps 3. render 4.componentDidMount | 1. getDerivedStateFromProps 2. shouldComponentUpdate 3. render 4. getSnaphsotBeforeUpdate 5. componentDidUpdate | componentWillUnmoun |
至于为什会有这些变化,看一下这篇文章 为什么会有 filber 架构?
三、函数式组件模拟几个常用的新版生命周期钩子函数
想要完全模拟所有类组件的生命周期钩子,是做不到的,也是没有必要的。比如 shouldComponentUpdate(nextProps, nextState, nextContext)
这个生命周期, 里面可能需要很多if判断不同的state, props,context 等信息,指定某一个state,这会导致大量业务逻辑跑到生命周期钩子里面去。
不管是react还是vue, 组件的生命周期无非就是三个阶段,挂载阶段、更新阶段、销毁阶段。
以下分别针对这三个阶段分别实现一个一个代表性的生命周期钩子:
1.挂载阶段 componentDidMount()
如果定义了 componentDidMount
方法,React 将会在组件被添加到屏幕上 (挂载) 后调用它。这里是设置数据获取、订阅监听事件或操作 DOM 节点的常见位置。
可以使用 useEffect 去模拟这个生命周期。
ts
useEffect(()=>{
console.log('componentDidMount...')
},[])
2.更新阶段 componentDidUpdate
可以封装一个钩子函数吗,用于模拟这个生命周期。。。但是,单纯使用useEffect
并给定依赖数组得话,在组件首次渲染的时候这个函数也会南北执行,这和只有数据更新的时候才执行不吻合,因此需要进一步封装。这里可以借助useRef
, useRef
类似UseState
, 都有记忆功能,但是,当值发生变化的时候,用useState
定义的satte
会导致组件的重新渲染,而useRef不会。
这里我定义一个钩子函数useComponentDidUpdate,函数签名是 (callBack:()=>undefind,relayOn:any[])=>undefined, 第一个参数是一个回调,第二个参数是需要监视变化属性。
ts
// useComponentDidUpdate.ts
export const useComponentDidUpdate = (callback:()=>undefind,relayOn:any[])=>{
// useRef 可以实现状态记忆
const ref = useRef(true);
useEffect(()=>{
// 如果是第一次调用就直接返回
if(ref.current){
ref.current = false
return
}
callBack?.();
},relayOn)
}
3.销毁阶段 componentWillUnmount
useEffect 接收一个函数,函数的返回值会在组件销毁之前调用。
ts
useEffect(()=>{
return ()=>{
console.log('componentWillUnmount....')
}
},[])