React 中最关键的聊聊知识点就是组件,在 React 16.8 之前(还没有 Hooks 前),函数我们的式组应用大多写成 Class 组件,因为 Class 组件有生命周期,组件能控制状态(state)。有何但函数式组件只能默默站在后面,不同说自己是聊聊木偶组件(也叫无状态组件),传来 props,函数展示UI 以下文字都基于有了 Hooks 后 函数式组件和类组件之间是式组否有什么根本上的区别? 具体可以看这篇文章:函数式组件与类组件有何不同? 因为在 React 中 props 是不可变(immutable)的,它们永远不会改变。组件然而,有何this 是不同可变(mutable)的 事实上,这就是聊聊类组件 this 存在的意义。React 本身会随着时间的函数推移而改变,以便你可以在渲染方法以及生命周期方法中得到最新的式组实例 函数式组件会捕获当前状态下的值,云服务器如果你使用定时器改变当前值的状态,那函数式组件显示的还是原来的值,而不是最新值。而类组件会一直获取最新值 只要一渲染,函数式组件就会捕获当前的值。而类组件即使渲染了,但是它的 this 会指向最新的实例 可以看线上Demo class ClassDemo extends React.Component { state = { value: "" }; showMessage = () => { alert("最新值为 " + this.state.value); }; handleMessageChange = (e) => { this.setState({ value: e.target.value }); }; handleClick = () => { setTimeout(this.showMessage, 3000); }; render() { return ( ); } 这样的结果是点击后获取到最新的值,而不是 3 秒前的值。为什么?因为 this 可变,3 秒之后执行 alert("最新值为 " + this.state.value)。 this.state.value 指向最新的值 如果类组件如果想保存原来的值该怎么做? 可以看线上Demo showMessage = (value) => { alert("最新值为 " + value); }; handleClick = () => { const { value } = this.state; setTimeout(() => this.showMessage(value), 3000); 可以解决,但点击时获取到当前的 user,高防服务器再传递给 this.showMessage,这样,即使 3 秒之后也是原来的值 缺点:每次都要从 this.props 中拿值,如果数据一多,写起来不符合人性 可以看线上Demo constructor(props) { super(props); this.showMessage = this.showMessage.bind(this); this.handleClick = this.handleClick.bind(this); 这个方法解决不了问题。我们的问题是我们从 this.props 中读取数据太迟了—— 读取时已经不是我们所需要使用的上下文 把方法写进 render 中,这样每次渲染时就能捕获住当时所用的 props 或者 state 可以看线上Demo class ClassDemo extends React.Component { state = { value: "" }; render() { const { value } = this.state; const showMessage = () => { alert("最新值为 " + value); }; const handleMessageChange = (e) => { this.setState({ value: e.target.value }); }; const handleClick = () => { setTimeout(showMessage, 3000); }; return ( ); } 但是这个方法很蠢,这个写法和函数式组件有什么区别呢?还不如用函数式组件呢 使用 useRef 保存最新的值,让组件获得最新的值 function MyComponent() { const ref = useRef(null); 首先,ref 与实例都扮演同样的角色,ref 对象是一个有 current 属性的一个容器 上次的例子我们用函数式组件就可以这样写: const FunctionDemo = () => { const [value, setValue] = useState(""); const refValue = useRef(""); const showMessage = () => { alert("最新值为 " + refValue.current); }; const handleMessageChange = (e) => { setValue(e.target.value); refValue.current = e.target.value; }; const handleClick = () => { setTimeout(showMessage, 3000); }; return ( ); 可以看线上Demo 这里笔者提出两个疑问: