react类组件
在 react16.8
推出之前,也就是2019年6月前,使用的是类组件。当然,现在基本上不使用它了,两者都用过的朋友们,应该能感受到类组件更加的复杂,但是在面试和学习过程中,提到它还是很有必要的,如果对于this
指向与JavaScript
中的类不太清楚的小伙伴可以提前熟悉一下。
一起走走this关键字走过的路------this的指向问题小美是一个白富美,她想在代码美如画的程序员小金面前介绍自己------你好, - 掘金
类组件的定义
react中规定了,类组件都必须继承
React.Component
或React.PureComponent
,并且,在类的方法中,必须至少实现render()
方法。由于我们今天主要是研究react函数组件如何模拟类组件的生命周期。接下来就着重介绍组件的渲染生命周期,走起。
一、基本定义
javascript
import React from 'react';
class MyComponent extends React.Component {
// 1. 构造函数(初始化)
constructor(props) {
super(props);
this.state = '' // 初始值
// 方法绑定
this.handleClick = this.handleClick.bind(this);
}
// 2. 静态生命周期方法
static getDerivedStateFromProps(props, state) {
// 返回要更新的state或null
return null;
}
componentWillMount() {
// 组件挂载前
}
// 3. 渲染方法(必需)
render() {
return <div>组件内容</div>;
}
// 4. 组件挂载完成
componentDidMount() {
// DOM操作、数据请求等
}
// 更新阶段
componentWillReceiveProps() {
// 外部接受到新的propos时执行
}
getDerivedStateFromProps(){
// 返回要更新的state或者null
}
shouldComponentUpdate(){
}
componentWillUpdate(){
}
Render() { }
componentDidUpdate() {
}
// 销毁阶段
componentWillUnmount() {
}
}
很多生命周期已经在react 16.8
之后被弃用了,我们使用useEffect
来模拟类组件的生命周期只要关注这几个重要的,就能满足日常的封装组件,接下来看在函数组件中,只用useEffec
t如何模拟这些生命周期。
注: 当getDerivedStateFromProps
存在时,componentWillMount、componentWillReceiveProps
这两个生命周期不会执行。静态方法取代了实例方法,实际上是这个静态方法会阻止 willMount
和 willReceiveProps
的执行。
函数组件
函数组件相对来说,对我们近几年学习react开发的同学们比较熟悉,也就是JSX/TSX语法,一个普通JavaScript函数,返回一个React元素(描述DOM的普通JS对象)。
一、useEffect
可能很多伙伴会在面试中提到useEffect
,相信大家都会这样回答:用于组件初始化数据获取、清除副作用函数、依赖第二个参数的变化再次执行这个useEffect......那么,它们分别对应了哪些,模拟了哪个生命周期呢?
1、componentDidMount
在组件挂载后执行,和useEffect传递入第二个参数空数组依赖等价,大多用于获取组件初始化数据,还有事件监听或者初始化第三方库组件实例。
javascript
componentDidMount() {
fetch('/api/data').then(data => this.setState({ data }));
}
// 函数组件
useEffect(() => {
fetch('/api/data').then(data => setData(data));
}, []);
// 类组件
componentDidMount() {
this.map = new MapLibre.Map({ container: 'map' });// 第三方组件,比如高德地图...
}
// 函数组件
useEffect(() => {
const map = new MapLibre.Map({ container: 'map' });
}, []);
2、componentWillReceiveProps
组件更新传值后执行,和useEffect第二个参数依赖组件的props
传参等价,用于propos
变化时,重置组件状态,获取新的数据。
scala
// 类组件
class MyComponent extends React.Component {
componentWillReceiveProps(nextProps) {
if (nextProps.userID !== this.props.userID) {
this.setState({ userData: null });
this.fetchUserData(nextProps.userID); // 根据新 props 请求数据
}
}
}
// 函数组件
function MyComponent({ userID }) {
const [userData, setUserData] = useState(null);
useEffect(() => {
if (userID) {
setUserData(null);
fetchUserData(userID); // 根据 props.userID 变化请求数据
}
}, [userID]); // 依赖数组:仅在 userID 变化时执行
return <div>{userData?.name}</div>;
}
3、componentDidUpdate
只要组件更新,就执行,相当于useEffect第二个参数什么不传。用于组件更新后需要同步DMO或者与不是React库(如谷歌地图)交互等情况使用。
4、computedWillUnmount
组件卸载时执行,在useEffect的第一个参数的返回值的箭头函数中执行。通常用于移除事件监听、移除定时器还有断开WebSocket连接等。
javascript
//类组件
class MyComponent extends React.Component {
componentDidMount() {
this.timer = setInterval(() => {
console.log("Timer tick");
}, 1000);
window.addEventListener("resize", this.handleResize);
}
componentWillUnmount() {
clearInterval(this.timer); // 清除定时器
window.removeEventListener("resize", this.handleResize); // 移除事件监听
}
handleResize = () => {
console.log("Window resized");
};
render() {
return <div>Check console for logs</div>;
}
}
// 函数组件
function MyComponent() {
useEffect(() => {
// 1. 设置定时器(effect 主体)
const timer = setInterval(() => {
console.log("Timer tick");
}, 1000);
// 2. 添加事件监听
const handleResize = () => console.log("Window resized");
window.addEventListener("resize", handleResize);
// 返回清理函数(会在卸载或依赖变化时执行)
return () => {
clearInterval(timer); // 清除定时器
window.removeEventListener("resize", handleResize); // 移除事件监听
};
}, []);
return <div>111</div>;
}
5、getDerivedStateFromProps
组件初始化后,每次接受新的props时调用,根据新的props计算并返回一个对象更新state,或者返回null不更新,相当于useState传入箭头函数内部执行。实际要配合useEffect依赖state值实现,我们这里展示执行时机。
javascript
// 类组件
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.value !== prevState.prevValue) {
return {
derivedValue: nextProps.value * 2, // 根据 props 计算新的 state
prevValue: nextProps.value, // 保存上一次的 props 用于比较
};
}
return null; // 不更新 state
}
// 函数组件
function Com () {
const [value,setValue] = useState(() =>{
conslog.log("getDerivedStateFromProps")
})
}