简单理解
1、类组件有生命周期,函数组件没有
2、类组件需要继承 Class,函数组件不需要
3、类组件可以获取实例化的 this,并且基于 this 做各种操作,函数组件不行
4、类组件内部可以定义并维护 state, 函数组件都称为无状态了,可以通过hooks实现。
函数组件更轻量与灵活,便于逻辑的拆分复用。
进阶理解
函数式组件捕获了渲染时所使用的值,这是两类组件最大的不同
创建组件LearnComponentDiff
import React from "react";
import FCComponent from "./fc-component";
import ClassComponent from "./class-component";
export default class LearnComponentDiff extends React.Component {
state = {
user: "名字",
};
render() {
return (
<>
<label>
<b>选择一个人查看关注: </b>
<select
value={this.state.user}
onChange={(e) => this.setState({ user: e.target.value })}
>
<option value="wangkai">名字</option>
<option value="zhangsan">张三</option>
<option value="lisi">李四</option>
</select>
</label>
<h1>欢迎关注 {this.state.user}!</h1>
<p>
<FCComponent user={this.state.user} />
<b> (函数组件)</b>
</p>
<p>
<ClassComponent user={this.state.user} />
<b> (类组件)</b>
</p>
<p>你能看出两者的不同吗</p>
</>
);
}
}
创建ClassComponent类组件
import React from 'react';
class ClassComponent extends React.Component {
showMessage = () => {
alert('选择的 ' + this.props.user);
}
handleClick = () => {
setTimeout(this.showMessage, 3000);
};
render() {
return <button onClick={this.handleClick}>尝试</button>;
}
}
export default ClassComponent;
点击页面后我们发现 初始化的props改变了! user 是通过 props 下发的,props不可改变,那么造成数据改变的原因就一定是 this 指向改变了。
真正的原因也确实如此,虽然props不可改变,但是this是可变的,this.props 的每次调用都会去获取最新的 this 值,这也是React保证数据实时性的重要手段。
那么就很清晰了,当showMessage最终执行时,此时的 this 绑定的是 张三对应的上下文,所以输出为 ‘已关注 张三’
创建FCComponent函数组件
import React from 'react';
function FCComponent(props) {
const showMessage = () => {
alert('已关注 ' + props.user);
}
const handleClick = () => {
setTimeout(showMessage, 3000);
};
return (
<button onClick={handleClick}>尝试</button>
);
}
export default FCComponent;
最终的输出值明显为 ‘选择的 名字’,props 会在函数执行的瞬间就被捕获,而 props 本身又是不可变值,所以我们可以确保从当前开始读取到的 props 都是最初捕获到的。当父组件传入新的 props 尝试重新渲染函数时,本质是基于新的 props 入参重新调用了一次函数,并不会影响上一次调用。这就是 Dan 所说的函数式组件捕获了渲染所使用的值,并且我们还能进一步意识到:函数组件真正将数据和渲染紧紧的绑定到一起了