当前位置: 首页 > 科技观察

想知道如何编写漂亮的React组件?

时间:2023-03-16 14:30:17 科技观察

在WalmartLabs的产品开发中,我们做了大量的codereview工作,这也保证了我有机会从众多优秀工程师的代码中学习到他们的代码风格和风格。在这篇博文中,我将分享我最喜欢的五个组件模式和代码片段。但首先我想谈谈为什么我们需要执着于提升代码的阅读体验。就像你有很多方法来打扮一只猫。如果你这样打扮你的猫:你可能认为萝卜青菜各有所爱,但代码本身要保证其可读性,尤其是在一个团队中,你的代码就是要被其他人阅读的。计算机不在乎这些,不管你扔给他们什么,他们都会老老实实解释,但你的队友不在乎,他们会把丑陋的代码扔回你脸上。所谓PrettyComponents应该包括以下特征:即使没有任何注释也易于理解比乱码性能更好更容易跟踪错误简洁明了,一句话价值万SFC:StatelessFunctionalComponent我认为是我们经常忽略的一种模式在开发中就是所谓的StatelessFunctionalComponent,但这是我最喜欢的React组件优化模式,没有之一。我喜欢这种模式不仅因为它们可以减少大量的样板代码,还因为它们可以有效地提高组件的性能。总而言之,SFC可以使您的应用程序运行得更快并且看起来更好。直观上,SFC指的是那些只有一个渲染功能的组件,但这种简单的改动可以避免很多无意义的检测和内存分配。下面通过一个实际的例子来看看SFC的具体功能。比如我们使用正统的React组件写法,可以得到如下代码:_handleClick=this._handleClick.bind(this);}_handleClick(suggestedUrl,event){event.preventDefault();this.props.onClick(suggestedUrl);}render(){return(RelatedSearches:{this.props.relatedQueries。map((query,index)=>this._handleClick(query.searchQuery,event)}key={index}>{query.searchText})});}}如果使用SFC模式,可以节省29%左右的代码:const_handleClick(suggestedUrl,onClick,event)=>{event.preventDefault();onClick(suggestedUrl);};constRelatedSearch=({relatedQueries,onClick})=>RelatedSearches:{relatedQueries.map((query,index)=>_handleClick(query.searchQuery,onClick,event)}key={index}>{query.searchText})}exportdefaultRelatedSearch;代码减少主要来自两个方面:没有构造函数(5行)ArrowFunction代替Render语句(4行)其实SFC最吸引人的地方不仅在于它只是其代码量的缩减,以及可读性的提升,SFC模式本身就是所谓纯组件的最佳实践范式,去掉了构造函数和点击事件回调函数_handleClick()提取组件可以让JSX代码更纯净,还有一个好处就是SFC将输入的Props变量定义为ArrowFunction的形式,即使用ObjectDestructring语法声明组件依赖的Props:constRelatedSearch=({relatedQueries,onClick})=>这样不仅让组件的props更清晰,也避免了冗余的this.props表达式,让代码更易读。***,我还要强调一下,虽然我很佩服SFC,但是不能滥用。最适合用SFC的地方就是你以前用纯组件的地方。在WalmartLabs中,我们使用Redux来管理应用的状态,这意味着我们大部分的组件都是纯组件,这给了SFC广阔的应用空间。一般来说,具有以下特点的组件肯定不适合使用SFC:需要自定义整个组件的生命周期管理,需要使用refsConditionalComponentsJSX本身不支持if表达式,但是我们可以使用逻辑表达式来避免使用代码拆分成不同的子模块,大致如下:render(){{this.props.isGrid?:}

}这种表达方式在渲染两者之一的时候很有效,但是对于选择性渲染一个的情况就不友好了,比如下面这种情况:render(){{this.props.isSoftSort?:null}
}确实有效,但看起来很奇怪。我们可以选择另一种更加语义友好的方式来实现这个功能,即使用逻辑和表达式,然后返回组件:render(){{!!this.props。isSoftSort&&
}不过这点也是见仁见智,大家可以根据自己的喜好来做。React和ReduxES2015中的ArrowSyntax包含很多美味的语法糖,我最喜欢的是ArrowNotation。此功能在编写组件时很有用:constSoftSort=({hardSortUrl,sortByName,onClick})=>{return(ShowingresultssortedbybothRelevanceand{sortByName}.onClick(ev,hardSortUrl)}>仅按{sortByName}排序
);};这个函数的作用是返回JSX对象,我们也可以忽略return语句:constSoftSort=({hardSortUrl,sortByName,onClick})=>ShowingresultssortedbybothRelevanceand{sortByName}.onClick(ev,hardSortUrl)}>Sortresultsby{sortByName}only代码行数减少了很多!另外一个我觉得很适合ArrowFunction的地方就是Redux的mapStateToProps函数:constmapStateToProps=({isLoading})=>{return({loading:isLoading,});};需要注意的是,如果返回的是Object,需要用大括号括起来:constmapStateToProps=({isLoading})=>({loading:isLoading});使用ArrowFunction优化的核心点是可以通过关注函数的重要部分来提高代码的整体可读性,避免模板代码过多带来的杂音。合理使用ObjectDestructing和SpreadAttributes大型组件往往会陷入this.props过长的困境,典型的如下:primaryOffer}productType={this.props.productType}productPageUrl={this.props.productPageUrl}inventory={this.props.inventory}submapType={this.props.submapType}ppu={this.props.ppu}isLoggedIn={this.props.isLoggedIn}gridView={this.props.isGridView}/>);}这么多Prop,看着可能会头疼。如果我们要将这些Props传递给下一层,大概会变成下面这个样子:render(){const{hidePriceFulfillmentDisplay,primaryOffer,productType,productPageUrl,inventory,submapType,ppu,isLoggedIn,gridView}=this。道具;返回();}先不考虑unKnownProps,我们可以使用解构赋值来实现这个功能:render(){constprops=this.props;return}方法定义简写***这个方法不一定有用,但是如果你想给Object添加功能,它还是可以让你的代码更漂亮,你可以使用ES2015MethodDefinitionShorthand来代替传统的ES5表达式,例如:如果你想设置一个默认的空方法,你也可以使用这个方法:ProductRating.defaultProps={onStarsClick(){}};