有段时间,这个问题标准回答是 class 组件提供了访问更多特性的权限(比如state),随着 Hooks 发布,那就不是这样了。

或许,你听过他们中哪个性能更好这样的问题,性能取决于你的代码做了什么而不是你选择用 function 还是class 组件。实际上这两者之间的性能差别是微不足道的,具体可以参考这个对比结果。

在这篇文章中,我们来看看它们两者之间最大的不同。

function 组件捕获渲染的值特性(captaure the rendered values)

事先申明:并不对 Function 与 Classes 进行优劣对比,而仅仅是说明 react 两种模式的不同。

对比下面两段代码:

Function Component:

function ProfilePage(props) {const showMessage = () => {alert("Followed " + props.user);};const handleClick = () => {setTimeout(showMessage, 3000);};return <button onClick={handleClick}>Follow</button>;
}复制代码

Class Component:

class ProfilePage extends React.Component {showMessage = () => {alert("Followed " + this.props.user);};handleClick = () => {setTimeout(this.showMessage, 3000);};render() {return <button onClick={this.handleClick}>Follow</button>;}复制代码

这两个组件代码都描述了同一个逻辑:点击按钮 3 秒后 alert 父级传入的用户名。通过这个 在线 Demo 完整代码,执行以下操作来说明两者的区别:

  1. 点击follow 按钮
  2. 在3秒弹窗之前,选择profile select
  3. 观察alert 弹出的值是什么

我们可以看到:

Class Component 展示的是修改后的值

Function Component 展示的是修改前的值:

这个例子中function 组件展示的才是我们期望的结果,因为我点了 follow 不希望因父级 props变化而改变原本期望的渲染结果,为什么 class 组件例子中出现这种情况?

class ProfilePage extends React.Component {showMessage = () => {alert("Followed " + this.props.user);};复制代码

原因是在 react 中 props 不可变(Immutable) 数据,但是在 react class 组件中,this 是可变的,因此 this.props 的调用会导致每次都访问最新的 props。上面的 showMessage 是在3秒后执行,这时props是最新的。而 Function Component 不存在 this.props 的语法,因此 props 总是不可变的。

如何解决这个问题?

一种方式是在事件绑定方法中读取这个 props ,然后传递给showMessage:

class ProfilePage extends React.Component {showMessage = (user) => {alert('Followed ' + user);};handleClick = () => {const {user} = this.props;setTimeout(() => this.showMessage(user), 3000);};render() {return <button onClick={this.handleClick}>Follow</button>;}
}复制代码

但是这样写代码显得臃肿啰嗦,而且,如果在showMessage中要调用其他方法,这个方法又要读取 this.props.somthing 或者 this.state.someting 又要传递this.props 或者 this.state,这样就很麻烦。

另一种方式就是在 render 函数中读取props:

class ProfilePage extends React.Component {render() {// Capture the props!const props = this.props;// Note: we are *inside render*.// These aren't class methods.const showMessage = () => {alert('Followed ' + props.user);};const handleClick = () => {setTimeout(showMessage, 3000);};return <button onClick={handleClick}>Follow</button>;}
}复制代码

这看起来很奇怪,加以简化,其实就是 function 组件。

Hooks 也具有 capture rendered values 特性

看下面代码:

function MessageThread() {const [message, setMessage] = useState('');const showMessage = () => {alert('You said: ' + message);};const handleSendClick = () => {setTimeout(showMessage, 3000);};const handleMessageChange = (e) => {setMessage(e.target.value);};return (<><input value={message} onChange={handleMessageChange} /><button onClick={handleSendClick}>Send</button></>);
}复制代码

在点击 Send 按钮后,再次修改输入框的值,3 秒后的输出依然是 点击前输入框的值。这说明 Hooks 同样具有 capture value 的特性。

如果我们想避开 capture values 的特性,就想获取最新的输入框的值怎么办?在 class 组件中,我们只需要访问 this.props 就行,因为 this 是可变的,能读取最新的props。

这里我们利用 useRef 可以规避 capture values 特性:

function MessageThread() {const [message, setMessage] = useState('');// Keep track of the latest value.const latestMessage = useRef('');useEffect(() => {latestMessage.current = message;});const showMessage = () => {alert('You said: ' + latestMessage.current);};const handleSendClick = () => {setTimeout(showMessage, 3000);};const handleMessageChange = (e) => {setMessage(e.target.value);};return (<><input value={message} onChange={handleMessageChange} /><button onClick={handleSendClick}>Send</button></>);
}复制代码

总结:

function 组件与 class 组件最大的不同是 function 组件能够捕获渲染的值,而 class 组件因为 react 中 this 是可变的,所以总是能获取最新的 props 。同样 hooks 和 function 组件一样具有 capture values 特性,利用useRef 可以避免 capture values 特性。

转载于:https://juejin.im/post/5cc190056fb9a0324a08afcd

Function Component 与 Class Component 有何不同?相关推荐

  1. SAP Spartacus后台CMS Component和Angular Component的映射关系

    a skeleton using CMS Components from backend: ConfigModule.withConfig({cmsComponents: {SimpleRespons ...

  2. SAP Spartacus维护CMS Component到Angular Component的源代码位置

    Spartacus界面上的banner,如下图所示,对应着HTML源代码里的cx-banner标签: cx-banner下面是cx-generic-link: 这个cx-generic-link包含一 ...

  3. 解决 Invalid component name: “404“. Component names should conform to valid custom element name ...

    问题描述 在 Vue 项目的控制台中出现以下报错信息: [Vue warn]: Invalid component name: "404". Component names sho ...

  4. 【uniapp】[Vue warn]: Invalid component name: “.-pages-Myblock-uni_myMessage“. Component names should

    使用uniapp开发时,页面报错chunk-vendors.js:3874 [Vue warn]: Invalid component name: ".-pages-Myblock-uni_ ...

  5. vue.runtime.esm.js?2b0e:619 [Vue warn]: Invalid component name: “__file“. Component names should con

    vue.runtime.esm.js?2b0e:619 [Vue warn]: Invalid component name: "__file". Component names ...

  6. Invalid component name: “Home,“. Component names should conform to valid custom element。。。控制台报错

    [Vue warn]: Invalid component name: "News,". Component names should conform to valid custo ...

  7. Invalid component name: “_Ctor“. Component names should conform to valid cus

    问题描述: 报了一堆component的错,但是不影响运行 解决方案: 在注册component的时候,加上一个大括号 <script> import login from './view ...

  8. 小程序插件封装Component报错 Component is not found in path……或 component is not defined

    小程序插件封装Component报错 小白程序猿,小程序在封装插件的时候遇到 Component报错,解决方式. # 提示为Component is not found in path--解决方式:排 ...

  9. html component标签,(九)Component标签

    本节知识点 组件标签 模板标签用的`` 概述 标签是vue自定义的标签.可以动态绑定我们的组件,根据数据不同更换不同的组件 componet标签 Title 点击我变换 var jsona = { t ...

最新文章

  1. 自贡市职称计算机考试,四川省自贡市2012年职称计算机考试时间
  2. python拷贝linux文件到windows_windows python文件拷贝到linux上执行问题
  3. nslookup命令反解ip_电脑网络基础知识:ipconfig/all命令及nslookupDns查询命令
  4. 设备驱动模型之device-driver
  5. nginx安装编译,动态添加模块及其各模块的作用
  6. java world_Java World中的GraphQL简介
  7. synchronized 和 reentrantlock 区别是什么_JUC源码系列之ReentrantLock源码解析
  8. JSF和Facelets的lifecircle
  9. 组合数(nyoj32)
  10. linux gvim 列编辑,Linux——vim编辑器
  11. MFC绘制图片闪烁详解
  12. java ojdbc6_JAVA JDBC在连接ORACLE数据库时出现ojdbc6.jar has no source 问题?
  13. 基于PaddlePaddle的OCR识别,识别车牌号
  14. 技术分享PPT整理(一):Bootstrap基础与应用
  15. 【javaIO流】--->IO流解析
  16. C语言:memcmp()---字符串比较
  17. Windows Server 2016-Powershell之客户端加域
  18. C语言-单词长度统计
  19. mysql等保测评命令_安全计算环境-二级等级保护测评指导和自动化脚本
  20. 凑辣荷丶换怂档屯览破擦丶笛丶北

热门文章

  1. @scheduled注解配置时间_探究 Spring 的定时任务配置
  2. c++fabs函数_二次函数背景下的菱形存在性问题
  3. python调包侠_拒绝调包侠,不需要高级算法和数据结构技巧
  4. python 调用 tensorflow.dll_解决windows上安装tensorflow时报错,“DLL load failed: 找不到指定的模块”的问题...
  5. python找字符串_Python如何实现查找字符串
  6. Magic Leap 2实测出炉:视场角增大20度,重量减轻20%,透光率低至0.3%让AR特效更逼真...
  7. 高校老师暑假狂补AI课背后:AI人才培养竞赛开跑
  8. 曾在字节实习的程序员小姐姐,教你一步提取动漫线稿!比用PS更清晰
  9. 《原神》米哈游突然押注脑机接口,CEO:10年内造出10亿人生活的虚拟世界
  10. 机器人用上AI后,拥有了堪比人类皮肤的触觉:轻松引线穿针、夹取鸡蛋丨Science子刊...