AICon 上海站|90%日程已就绪,解锁Al未来! 了解详情
写点什么

乾坤大挪移!React 也能 “用上” computed 属性

  • 2021-02-01
  • 本文字数:2395 字

    阅读完需:约 8 分钟

乾坤大挪移!React 也能 “用上” computed 属性

前言,关于计算属性

初次见到计算属性一词,是在 Vue 官方文档 《计算属性和侦听器》 一节中,文章中是这样描述计算属性的:


模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。


回想我们编写的 React 代码,是否也在 JSX(render 函数)中放入了太多的逻辑导致 render 函数过于庞大,难以维护?


React 中的计算属性


说到 React 之前,我们先看下 Vue,在 Vue 中,计算属性主要有以下两点特性:


  1. 计算属性以声明的方式创建依赖关系,依赖的 data 或 props 变更会触发重新计算并自动更新。

  2. 计算属性是基于它们的响应式依赖进行缓存的。


而在 React 中,计算属性也是经常可见,相信各位熟悉 React 的读者都写过类似下面的代码:


import React, { Fragment, Component } from'react';
class Example extends Component { state = { firstName: '', lastName: '', };
render() { // 在 render 函数中处理逻辑 const { firstName, lastName } = this.state; const fullName = `${firstName} ${lastName}`; return<Fragment>{fullName}</Fragment>; }}
复制代码


在上面的代码里,render 函数里的 fullName 依赖了 props 中的 firstName 和 lastName 。firstName 或 lastName 变更之后,变量 fullName 都会自动更新。其实现原理是 props 以及 state 的变化会导致 render 函数调用,进而重新计算衍生值。


虽然能实现计算,但我们还是把计算逻辑放入了 render 函数导致了它的臃肿,这并不优雅。更好的做法是把计算逻辑抽出来,简化 render 函数逻辑:


class Example extends Component {  state = {    firstName: '',    lastName: '',  };
// 把 render 中的逻辑抽成函数,减少render函数的臃肿 renderFullName() { const { firstName, lastName } = this.state; return`${firstName} ${lastName}`; }
render() { const fullName = this.renderFullName(); return<Fragment>{fullName}</Fragment>; }}
复制代码


如果你对 Vue 很了解,你肯定知道其 computed 计算属性,底层是使用了 getter,只不过是对象的 getter。那么在 React 中,我们也可以使用类的 getter 来实现计算属性:



class Example extends Component { state = { firstName: '', lastName: '', };
// 通过getter而不是函数形式,减少变量 get fullName() { const { firstName, lastName } = this.state; return`${firstName} ${lastName}`; }
render() { return<Fragment>{this.fullName}</Fragment>; }}
复制代码


进一步,使用 memoization 优化计算属性


上文有提到在 Vue 中计算属性对比函数执行,会有缓存,减少计算。因为计算属性只有在它的相关依赖发生改变时才会重新求值。


这就意味着只要  firstName 和 lastName 还没有发生改变,多次访问 fullName 计算属性会立即返回之前的计算结果,而不必再次执行函数。


对比之下,React 的 getter 是否也有缓存这个优势??? 答案是:没有。React 中的 getter 并没有做缓存优化


不过不用失望,我们可以使用记忆化技术(memoization)来优化我们的计算属性,达到和 Vue 中计算属性一样的效果。我们需要在项目中引入 memoize-one 库,代码如下:


import memoize from'memoize-one';import React, { Fragment, Component } from'react';
class Example extends Component { state = { firstName: '', lastName: '', };
// 如果和上次参数一样,`memoize-one` 会重复使用上一次的值。 getFullName = memoize((firstName, lastName) =>`${firstName} ${lastName}`);
get fullName() { returnthis.getFullName(this.state.firstName, this.state.lastName); }
render() { return<Fragment>{this.fullName}</Fragment>; }}
复制代码


再进一步,使用 React Hooks 优化计算属性


上文在 React 中使用了 memoize-one 库实现了类似 Vue 计算属性(computed)的效果 —— 基于依赖缓存计算结果。得益于 React 16.8 新推出的 Hooks 特性,我们可以对逻辑进行更优雅的封装,对 Hooks 还不够了解的小伙伴可以先阅读我们团队另一篇文章 《看完这篇,你也能把 React Hooks 玩出花


此处,我们需要用到 useMemo。官方对 useMemo 的介绍在 这里(https://zh-hans.reactjs.org/docs/hooks-reference.html#usememo),详情请移步查看。简单的说,就是我们传入一个 回调函数 和一个 依赖列表,React 会在依赖列表中的值变化时,调用这个回调函数,并将回调函数返回的结果进行缓存:


import React, { useState, useMemo } from'react';
function Example(props) { const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); // 使用 useMemo 函数缓存计算过程 const renderFullName = useMemo(() =>`${firstName} ${lastName}`, [ firstName, lastName, ]);
return<div>{renderFullName}</div>;}
复制代码


总结


本文介绍了在 React 中如何实现类似 Vue 计算属性(computed)的效果 —— 基于依赖缓存计算结果,实现逻辑计算与视图渲染的解耦,降低 render 函数的复杂度。


从业务开发角度来讲,Vue 提供的 API 极大地提高了开发效率。React 虽然在某些场景下,没有官方的同类原生 API 支持,但得益于活跃的社区,工作中遇到的问题总能找到解决方案。且在摸索这些解决方案的同时,我们还能学习到诸多经典的编程思想,帮助我们更合理的运用框架,用技术解决业务问题。



头图:Unsplash

作者:不二

原文:https://mp.weixin.qq.com/s/Fv69IvuR4FhyFQbLO7DLMg

原文:乾坤大挪移!React 也能 “用上” computed 属性

来源:政采云前端团队 - 微信公众号 [ID:Zoo-Team]

转载:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2021-02-01 00:002516

评论

发布
暂无评论
发现更多内容

JVM课程作业

追随哆咪

SaaS 行业垂直数据库需求5点思考:成本、计费、库表量、多云、低代码

B Impact

金三银四吃透这份微服务笔记,面试保准涨10K+

小小怪下士

Java 程序员 面试 微服务

Python学生管理系统

漫步桔田

详解Apache Sentry->Ranger平滑升级方案

华为云开发者联盟

开发 华为云 企业号 2 月 PK 榜 华为云开发者联盟

如何使用开源构建可信赖的人工智能

开源雨林

人工智能 开源

time_point 的基本用法举例

老王同学

C++11

2023-02-24:请用go语言调用ffmpeg,解码mp4文件并保存为YUV420SP格式文件,采用YUV420P转YUV420SP的方式。

福大大架构师每日一题

golang ffmpeg 福大大

Python银行取款系统

漫步桔田

2023年1月综合预订类APP用户洞察——旅游市场复苏明显,三年需求春节集中释放

易观分析

App 旅游 后疫情时代

Amazon S3 服务15岁生日快乐!

亚马逊云科技 (Amazon Web Services)

数据库 云计算

2023最新版网络安全保姆级指南,手把手带你从零基础进阶渗透攻防工程师

网络安全学海

黑客 网络安全 信息安全 计算机 渗透测试

DNSPod十问简丽荣:国产数据库的月亮与六便士

酷克数据HashData

Airbyte,数据集成的未来

CnosDB

数据库 时序数据库 开源社区 CnosDB

FL Studio2023中文电脑版本下载

茶色酒

FL Studio2023

你知道CleanMyMac是什么吗软件?好用吗

茶色酒

CleanMyMac X2023

数据库行业的 “叛逆者”:大数据已“死”,MotherDuck 当立

CnosDB

数据库 时序数据库 开源社区 CnosDB

最新攻略!掌握这些技巧,推特视频下载so easy!

frank

twitter

华为云 UCS (On-Premises):运行在您本地数据中心的CCE集群

华为云开发者联盟

云计算 后端 华为云 企业号 2 月 PK 榜 华为云开发者联盟

推荐系统[八]算法实践总结V1:淘宝逛逛and阿里飞猪个性化推荐:召回算法实践总结【冷启动召回、复购召回、用户行为召回等算法实战】

汀丶人工智能

自然语言处理 推荐系统 推荐算法 推荐引擎算法

FL Studio21水果最新完整版音乐编曲软件

茶色酒

FL Studio 21 FL Studio21

Python电影售票系统

漫步桔田

秒懂算法 | 回归算法中的贝叶斯

TiAmo

算法 贝叶斯公式 贝叶斯算法

ABBYY16绿色免费pdf编辑器下载

茶色酒

ABBYY16

JPEX宣布将在香港申请加密货币交易牌照,促进全球生态布局

股市老人

收割不易,五面Alibaba终拿Java岗offer

程序知音

Java java面试 Java进阶 后端技术 Java面试八股文

零基础解读ChatPGT:对人类未来工作是威胁还是帮助?

华为云开发者联盟

人工智能 华为云 ChatGPT 企业号 2 月 PK 榜 华为云开发者联盟

Oracle在“AI云战”比AWS、Azure的优势:多云、无竞争、收费低训练快

B Impact

Stripe 不再受硅谷宠爱:高层与销售分裂、限制型股票拖后腿

B Impact

7 理解企业的战略

涛哥 数字产品和业务架构

企业架构 业务架构 战略

三天吃透MySQL八股文(2023最新整理)

程序员大彬

Java MySQL 数据库

乾坤大挪移!React 也能 “用上” computed 属性_大前端_政采云前端团队_InfoQ精选文章