在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)=>className="related-search-link"onClick={(event)=>this._handleClick(query.searchQuery,event)}key={index}>{query.searchText})});}}如果使用SFC模式,可以节省大约29%的代码:,onClick})=>RelatedSearches:{relatedQueries.map((query,index)=>className="related-search-link"onClick={(event)=>_handleClick(query.searchQuery,onClick,event)}key={index}>{query.searchText})}exportdefaultRelatedSearch;代码量的减少主要来自两个方面:无构造函数(5行)和ArrowFunction代替Render声明(4行)其实,SFC最迷人的地方不仅在于其代码量的减少,还有可读性的提高。SFC模式本身就是所谓纯组件的最佳实践范式,将Createaconstructor和提取点击事件回调函数_handleClick()从组件中移除,可以让JSX代码更加纯净。还有一个好处就是SFC以ArrowFunction的形式定义了输入的Props变量,即用ObjectDestructring的语法声明了组件所依赖的Props:constRelatedSearch=({relatedQueries,onClick})=>这样不仅使得组件的Props更清晰,可以避免冗余的this.props表达式,使代码更具可读性。***,我还要强调一下,虽然我很佩服SFC,但是也不能滥用。使用SFC的最佳位置是您以前使用纯组件的地方。在WalmartLabs中,我们使用Redux来管理应用程序的状态,这意味着我们的大部分组件都是纯组件,这给了SFC广阔的应用空间。一般来说,具有以下特点的组件肯定不适合使用SFC:需要自定义整个组件的生命周期管理,需要使用refsConditionalComponentsJSX本身不支持if表达式,但是我们可以使用逻辑表达式来avoidusing代码分成不同的子模块,大致如下:render(){{this.props.isGrid?:}}这个表达式在渲染两者之一时非常有效,但是对于选择性渲染其中一个的情况非常不友好,比如下面这种情况:render(){{this.props.isSoftSort?:null}}这个确实可以,但是看起来很奇怪。我们可以选择另一种语义更友好的方式来实现这个功能,即使用逻辑和表达式,然后返回组件:render(){{!!this.props.isSoftSort&&}}不过这也是见仁见智,大家按照自己的喜好来就好。React和ReduxES2015中的ArrowSyntax包含很多美味的语法糖,我最喜欢的是ArrowNotation。这个特性在编写组件时很有用:constSoftSort=({hardSortUrl,sortByName,onClick})=>{return(ShowingresultssortedbybothRelevanceand{sortByName}.href={`?${hardSortUrl}`}onClick={(ev)=>onClick(ev,hardSortUrl)}>Sortresultsby{sortByName}only);};这个函数的作用是返回JSX对象,我们也可以忽略返回语句:constSoftSort=({hardSortUrl,sortByName,onClick})=>ShowingresultssortedbybothRelevanceand{sortByName}.href={`?${hardSortUrl}`}onClick={(ev)=>onClick(ev,hardSortUrl)}>Sortresultsby{sortByName}only代码行数少了很多!另外一块我觉得非常适合ArrowFunction的是Redux的mapStateToProps函数:constmapStateToProps=({isLoading})=>{return({loading:isLoading,});};需要注意的是,如果返回Object,需要用大括号括起来:constmapStateToProps=({isLoading})=>({loading:isLoading});使用ArrowFunction优化的核心点是可以通过关注函数的重要部分来提高代码的整体可读性,避免过多的模板代码噪声。ObjectDestructing和SpreadAttributes的合理使用大型组件经常会遇到this.props过长的困境,典型的如下:}productType={this.props.productType}productPageUrl={this.props.productPageUrl}inventory={this.props.inventory}submapType={this.props.submapType}ppu={this.props.ppu}isLoggedIn={this...看起来像:render(){const{hidePriceFulfillmentDisplay,primaryOffer,productType,productPageUrl,inventory,submapType,ppu,isLoggedIn,gridView}=this.props;return(hidePriceFulfillmentDisplay={hidePriceFulfillmentDisplay}primaryOffer={primaryPriceUrl}productType}={productTyper={productPageUrl}inventory={inventory}submapType={submapType}ppu={ppu}isLoggedIn={isLoggedIn}gridView={isGridView}/>);}暂时忽略未知的Props,我们可以使用解构赋值来实现这个功能:render(){constprops=this.props;return}MethodDedefinitionShorthand***这个方法不一定有用,但还是可以让你的代码更漂亮。如果想给Object添加功能,可以使用ES2015MethodDefinitionShorthand代替传统的ES5表达式,比如:Link.defaultProps={onClick(event){event.preventDefault();Logger.log(event);}};如果你想设置一个默认的清空方法,也可以使用这个方法:ProductRating.defaultProps={onStarsClick(){}};
