如何写出漂亮的React组件

在Walmart Labs的产品开发中,我们进行了大量的Code
Review工作,这也保证了我有机会从很多优秀的工程师的代码中学习他们的代码风格与样式。在这篇博文里我会分享出我最欣赏的五种组件模式与代码片。不过我首先还是要谈谈为什么我们需要执着于提高代码的阅读体验。就好像你有很多种方式去装扮一只猫,如果你把你的爱猫装扮成了如下这样子:

你或许可以认为萝卜青菜各有所爱,但是代码本身是应当保证其可读性,特别是在一个团队中,你的代码是注定要被其他人阅读的。电脑是不会在意这些的,不管你朝它们扔过去什么,它们都会老老实实的解释,但是你的队友们可不会这样,他们会把丑陋的代码扔回到你的脸上。而所谓的Pretty
Components,应该包含如下的特性:

  • 即使没有任何注释的情况下也易于理解
  • 比乱麻般的代码有更好的性能表现
  • 更易于进行Bug追溯
  • 简洁明了,一句顶一万句

SFC:Stateless Functional Component

我觉得我们在开发中经常忽略掉的一个模式就是所谓的Stateless Functional
Component,不过这是我个人最爱的React组件优化模式,没有之一。我喜爱这种模式不仅仅因为它们能够减少大量的模板代码,而且因为它们能够有效地提高组件的性能表现。总而言之,SFC能够让你的应用跑的更快,长的更帅。

直观来看,SFC就是指那些仅有一个渲染函数的组件,不过这简单的改变就可以避免很多的无意义的检测与内存分配。下面我们来看一个实践的例子来看下SFC的具体作用,譬如:

如果我们用正统的React组件的写法,可以得出如下代码:


  1. export default class RelatedSearch extends React.Component {  
  2. constructor(props) {  
  3. super(props);  
  4. this._handleClick = this._handleClick.bind(this);  
  5. }  
  6. _handleClick(suggestedUrl, event) {  
  7. event.preventDefault();  
  8. this.props.onClick(suggestedUrl);  
  9. }  
  10. render() {  
  11. return (  
  12. Related Searches:  
  13. {this.props.relatedQueries.map((query, index) =>  
  14. className="related-search-link"  
  15. onClick={(event) =>  
  16. this._handleClick(query.searchQuery, event)}  
  17. key={index}>  
  18. {query.searchText}  
  19. )}  
  20. );  
  21. }  

而使用SFC模式的话,大概可以省下29%的代码:


  1. const _handleClick(suggestedUrl, onClick, event) => {  
  2. event.preventDefault();  
  3. onClick(suggestedUrl);  
  4. };  
  5. const RelatedSearch = ({ relatedQueries, onClick }) =>  
  6. Related Searches:  
  7. {relatedQueries.map((query, index) =>  
  8. className="related-search-link"  
  9. onClick={(event) =>  
  10. _handleClick(query.searchQuery, onClick, event)}  
  11. key={index}>  
  12. {query.searchText}  
  13. )}  
  14. export default RelatedSearch; 

代码量的减少主要来源两个方面:

  • 没有构造函数(5行)
  • 以Arrow Function的方式替代Render语句(4行)

实际上,SFC最迷人的地方不仅仅是其代码量的减少,还有就是对于可读性的提高。SFC模式本身就是所谓纯组件的一种最佳实践范式,而移除了构造函数并且将_handleClick()这个点击事件回调函数提取出组件外,可以使JSX代码变得更加纯粹。另一个不错的地方就是SFC以Arrow
Function的方式来定义了输入的Props变量,即以Object Destructring语法来声明组件所依赖的Props:


  1. const RelatedSearch = ({ relatedQueries, onClick }) => 

这样不仅能够使组件的Props更加清晰明确,还能够避免冗余的this.props表达式,从而使代码的可读性更好。

最后,我还想要强调下虽然我很推崇SFC,不过也不能滥用它。最合适使用SFC的地方就是之前你用纯组件的地方。在Walmart
Labs中,我们使用Redux来管理应用的状态,也就意味着我们绝大部分的组件都是纯组件,也就给了SFC广阔的应用空间。一般来说,有以下特征的组件式绝对不适合使用SFC的:

  • 需要自定义整个组件的生命周期管理
  • 需要使用到refs

Conditional Components

JSX本身不支持if表达式,不过我们可以使用逻辑表达式的方式来避免将代码切分到不同的子模块中,大概是如下样子:


  1. render() {  
  2. {this.props.isGrid  
  3. ?  
  4. : }  

这种表达式在二选一渲染的时候很有效果,不过对于选择性渲染一个的情况很不友好,譬如如下的情况:


  1. render() {  
  2. {this.props.isSoftSort  
  3. ?  
  4. : null  
  5. }  

这样子确实能起作用,不过看上去感觉怪怪的。我们可以选用另一种更加语义化与友好的方式来实现这个功能,即使用逻辑与表达式然后返回组件:


  1. render() {  
  2. {!!this.props.isSoftSort && }  

不过这一点也是见仁见智,每个人按照自己的喜好来就行了。

Arrow Syntax In React And Redux

ES2015里包含了不少可口的语法糖,我最爱的就是那个Arrow Notation。这个特性在编写组件时很有作用:


  1. const SoftSort = ({ hardSortUrl, sortByName, onClick }) => {  
  2. return (  
  3. Showing results sorted by both Relevance and {sortByName}.  
  4. href={`?${hardSortUrl}`}  
  5. onClick={(ev) => onClick(ev, hardSortUrl)}>  
  6. Sort results by {sortByName} only  
  7. );  
  8. }; 

该函数的功能就是返回JSX对象,我们也可以忽略return语句:


  1. const SoftSort = ({ hardSortUrl, sortByName, onClick }) =>  
  2. Showing results sorted by both Relevance and {sortByName}.  
  3. href={`?${hardSortUrl}`}  
  4. onClick={(ev) => onClick(ev, hardSortUrl)}>  
  5. Sort results by {sortByName} only 

代码行数又少了不少咯!

另一块我觉得非常适用Arrow Function的地方就是Redux的mapStateToProps函数:


  1. const mapStateToProps = ({isLoading}) => {  
  2. return ({  
  3. loading: isLoading,  
  4. });  
  5. }; 

需要注意的是,如果你返回的是Object,你需要包裹在大括号内:


  1. const mapStateToProps = ({isLoading}) => ({  
  2. loading: isLoading  
  3. }); 

使用Arrow Function优化的核心点在于其能够通过专注于函数的重要部分而提升代码的整体可读性,并且避免过多的模板代码带来的噪音。

合理使用Object Destructing与Spread Attributes

大的组件往往受困于this.props过长的窘境,典型的如下所示:


  1. render() {  
  2. return (  
  3. hidePriceFulfillmentDisplay=  
  4. {this.props.hidePriceFulfillmentDisplay}  
  5. primaryOffer={this.props.primaryOffer}  
  6. productType={this.props.productType}  
  7. productPageUrl={this.props.productPageUrl}  
  8. inventory={this.props.inventory}  
  9. submapType={this.props.submapType}  
  10. ppu={this.props.ppu}  
  11. isLoggedIn={this.props.isLoggedIn}  
  12. gridView={this.props.isGridView}  
  13. />  
  14. );  

这么多的Props估计看着都头疼,如果我们要将这些Props继续传入下一层,大概就要变成下面这个样子了:


  1. render() {  
  2. const {  
  3. hidePriceFulfillmentDisplay,  
  4. primaryOffer,  
  5. productType,  
  6. productPageUrl,  
  7. inventory,  
  8. submapType,  
  9. ppu,  
  10. isLoggedIn,  
  11. gridView  
  12. } = this.props;  
  13. return (  
  14. hidePriceFulfillmentDisplay={hidePriceFulfillmentDisplay}  
  15. primaryOffer={primaryOffer}  
  16. productType={productType}  
  17. productPageUrl={productPageUrl}  
  18. inventory={inventory}  
  19. submapType={submapType}  
  20. ppu={ppu}  
  21. isLoggedIn={isLoggedIn}  
  22. gridView={isGridView}  
  23. />  
  24. );  

暂时不考虑unKnown Props,我们可以使用解构赋值来实现这个功能:


  1. render() {  
  2. const props = this.props;  
  3. return  
  4. }  
  5. Method Definition Shorthand 

最后这个方法不一定多有用,不过还是能让你的代码变得更加漂亮。如果你希望在Object中添加函数,你可以使用ES2015 Method Definition Shorthand来代替传统的ES5的表达式,譬如:


  1. Link.defaultProps = {  
  2. onClick(event) {  
  3. event.preventDefault();  
  4. Logger.log(event);  
  5. }  
  6. };  
  7. 如果你想设置一个默认的空方法,也可以利用这种方式:  
  8. ProductRating.defaultProps = {  
  9. onStarsClick() {}  
  10. }; 

作者:王下邀月熊_Chevalier

来源:51CTO

时间: 2024-10-31 04:31:46

如何写出漂亮的React组件的相关文章

写出漂亮代码的七种方法

首先我想说明我本文阐述的是纯粹从美学的角度来写出代码,而非技术.逻辑等.以下为写出漂亮代码的七种方法: 1.尽快结束 if 语句 例如下面这个JavaScript语句,看起来就很恐怖: function findShape(flags, point, attribute, list) { if(!findShapePoints(flags, point, attribute)) { if(!doFindShapePoints(flags, point, attribute)) { if(!fin

急求解决-用Java如何写出漂亮的图形

问题描述 用Java如何写出漂亮的图形 记得以前在csdn上面看到了一篇博文,是用java写的很多漂亮的线条组合在一起形成的图片,非常的美观.求大神指教下,给点资料看看

用HTML和CSS写出漂亮正规的BLOG

正确使用a标签 超链接是blog中用的最多的html标签,它用来链接到其他的文章或者站点链接,建议大家用a标签时将下列属性都添加上: href:设置链接的url地址或锚点 target:设置鼠标点击链接后的目标窗口或框架页面,一般常用的是target="_blank",表示新开一个窗口打开链接,向在当前页面打开链接就不用加这个属性了 title:设置鼠标移动到链接上时显示的提示信息 rel:这个是最近才开始流行的新属性.rel="nofollow"表示禁止搜索引擎从

在CSDN上写出漂亮博文

[边讲边演示--请点下面的视频链接] [要点] 问题: CSDN的博文中插入代码,可以排版出很漂亮的效果,但是 处理不当,有时变得很难看 解决方案: 在集成开发环境(IDE)中编辑好后再往博客中放: 选用插入代码的工具(注意选择语言): 懂一些HTML,直接编辑"源代码",处理意外的情况  <p>- </p>  <br>  <a href="http://www.ytu.edu.cn">链接烟大</a>  

XHTML+CSS写出正规的BLOG

 Blog的全名应该是Web log,中文意思是"网络日志",后来缩写为Blog,而博客(Blogger)就是写Blog的人.从理解上讲,博客是"一种表达个人思想.网络链接.内容,按照时间顺序排列,并且不断更新的出版方式".简单的说博客是一类人,这类人习惯于在网上写日记. 如何应用HTML和CSS写出漂亮正规的BLOG:       正确使用a标签       超链接是blog中用的最多的html标签,它用来链接到其他的文章或者站点链接,建议大家用a标签时将下列属性

XHTML+CSS写出正规BLOG

 Blog的全名应该是Web log,中文意思是"网络日志",后来缩写为Blog,而博客(Blogger)就是写Blog的人.从理解上讲,博客是"一种表达个人思想.网络链接.内容,按照时间顺序排列,并且不断更新的出版方式".简单的说博客是一类人,这类人习惯于在网上写日记. 如何应用HTML和CSS写出漂亮正规的BLOG:       正确使用a标签       超链接是blog中用的最多的html标签,它用来链接到其他的文章或者站点链接,建议大家用a标签时将下列属性

高性能 React 组件

前言 组件的重新渲染 说到 React 组件,肯定离不开组件的 props 和 state,我们可以在 props 和 state 存放任何类型的数据,通过改变 props 和 state,去控制整个组件的状态.当 props 和 state 发生变化时,React 会重新渲染整个组件,组件重新渲染的过程可简化如下图: 当组件的 props 或 state 变化,React 将会构建新的 virtual DOM,使用 diff 算法把新老的 virtual DOM 进行比较,如果新老 virtu

如何实现 React 组件的可复用性

本文讲的是如何实现 React 组件的可复用性, 可复用性一词是当今软件工程领域上最为常见的流行词之一.可复用性早已成为大量不同框架.工具乃至模型都需要承诺的一种特性,且每一个所实现的方式与对该特性的诠释都各不相同. 那么,可复用性到底指的是什么? 真正的可复用性指的并非是一种特定的流程,而是一个开发策略.因而,在构建可复用组件时,开发者必须得把可复用性牢记在脑海里.因为,这将涉及到无比细致的规划及善解人意的 API 设计.再者,既然可复用性早已被现代的开发工具与框架所支持且倡导,那么我们就不能

How to Achieve Reusability with React Components - 如何实现 React 组件的可复用性 Back

本文讲的是How to Achieve Reusability with React Components - 如何实现 React 组件的可复用性 Back, 原文地址:How to Achieve Reusability with React Components 原文作者:Alex Grigoryan 译文出自:掘金翻译计划 译者:aleen42 校对者:Professor-Z.sqrthree.xiaoheiai4719 可复用性一词是当今软件工程领域上最为常见的流行词之一.可复用性早已