在React文档中, 当我搜索class component时, 出来的目录是API参考 > 过时的React API > PureComponent
为什么要去了解一个过时不被官方推荐的东西呢, 每个东西都有他的更新迭代, 在我学习hook的时候, 得知他是可以代替class组件的部分功能时, 我需要了解class组件来促进我对hook的理解. (实话是因为我在面试时被问了说有没有用过类组件, 我胡诌了几句后扯到hook逻辑复用上去后他问我类组件怎么实现逻辑复用, ok, 面试挂了)
React类组件
首先关于类组件要提起Component
Component是一个JavaScript类, 被定义为React组件的基类, 如果你想要使用类组件, 那么我们需要继承内置的Component类并定义render方法
我们接下来简单说一下类组件的几个方法
- render: 类组件中唯一的必须方法, 指定你想要在屏幕中渲染的内容
- 这个方法是什么时候调用的, 我们可以去结合React的生命周期去解释, 在React的初始化, 更新过程中会调用render, 但如果说定义了
shouldComponentUpdate
并且该生命周期返回了false, 那么render是不会被调用的
- 这个方法是什么时候调用的, 我们可以去结合React的生命周期去解释, 在React的初始化, 更新过程中会调用render, 但如果说定义了
- context: 类组件可以通过this.context访问context, 这里就不作详细解释的, useContext平替
- props: 可以使用this.props访问一个类组件的props.(也就是用于父子组件之间的数据传递)
- state: 类组件的state, 必须是一个对象, 不能直接被改变只能通过调用setState并传入新的state对象, 这里其实就是useState这个hook的平替
- cuonstructor(props): 会在挂载之前运行, 在较新的语法已经很少使用到constructor
- 是唯一一个能直接给this.state的地方, 其余地方需要使用this.setState
- super(props): 需要在其他的声明之前调用, 如果不调用那么this.props在constructor运行时就会为undefined 这里如果想要详细了解的话推荐一篇文章 我们为什么要写 super(props)?
综上所述的一些属性和更新, 我们现在可以写出一个这样的类组件
class Counter extends Component{
// counstructor原先的写法
constructor(props) {
super(props);
this.state = { counter : 0 };
this.handleClick = this.handleClick.bind(this);
}
// constructor重写的新写法
state = {
count: 1
}
handleClick = () =>{
...
}
render(){
return(
<div>
{this.state.count}
</div>
)
}
}
了解了上面这些后, 我们其实已经可以写出一个简单的类组件, 那么类组件还有什么内容呢
这里我们来解释下一波函数, 也就是我们所说的React生命周期函数中的某几个, 生命周期就到另外的文章去总结了, 这边主要讲一下这里三个生命周期函数和类组件的关系, 其实我们可以先这样理解, 这三个函数组合在一起就是useEffect()的平替
- componentDidMount : React在将组件添加到屏幕上后调用它, 在这里可以设置数据获取, 监听事件或者操作dom节点
- componentDidUpdate : 在组件更新props或者state重新渲染后立即调用它, 可以在一次更新后使用该方法来操作dom(在shouldComponentUpdate被定义并且返回false的情况下不会被调用)
- componentWillUnmount: 会在组件被移除屏幕之前调用它, 一般用来取消数据获取或者移除监听事件
class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};
componentDidMount() {
this.setupConnection();
}
componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}
componentWillUnmount() {
this.destroyConnection();
}
// ...
}
那么有了上述的这些信息, 我们已经可以通过类组件来实现大部分功能, 如果有其他的一些需求例如错误捕获, 类组件也有提供一些对应的函数去处理, 包括其实还有一些其他的生命周期函数没有讲到, 这边有想详细了解的可以看下React的官方文档, 相对来说其实会比大部分文章都细致很多
那么这个时候我们再去看, 为什么类组件不被推荐, 我们这边可以把上面的代码去使用函数组件+hook的写法实现一遍, 可以明显的感知到, 在代码量层面会有一个明显的区别
那么类组件相比于函数组件多了什么功能
- getSnapshotBeforeUpdate : 在dom发生更改之前捕获一些信息例如滚动的位置作为参数传递给componetDidUpdate, 例如在组件更新期间保留用户滚动位置
- getDerivedStateFromError & componentDidCatch : 定义错误边界(在函数组件中想要实现该功能需要编写一个ErrorBoundary组件或使用对应的包)
以上两个功能其实也从侧面说明了为什么类组件不被推荐, 但是又没有完全被废弃, 或许等到类组件的功能完全被函数组件复刻的时候, 也就是类组件彻底被废弃的时候
那么我们再继续看看导致我面试挂掉原因之一的类组件逻辑复用, 我们可以通过抽离自定义hook的方式实现函数组件内的逻辑复用, 那么类组件的逻辑复用需要通过什么呢 -> 高阶组件看了眼还是有点头大…如果有会总结的朋友可以总结一下, 万分感谢
总体看下来, 看完一个类组件, 了解了生命周期以及一些Hook的设计原理包括说函数组件不能实现的某些功能.
希望这篇文章可以帮助到像我一样没有写过类组件不了解类组件的你
原文链接:https://juejin.cn/post/7343895308931727410 作者:资深摸鱼师