React进阶学习之组件的解耦之道
程序员文章站
2022-05-14 19:25:06
前言
众所周知,react中的组件非常的灵活可扩展,不过随着业务复杂度的增加和许多外部工具库的引入,组件往往也会显得浮肿,接下来我们就一起来看看常见的几种,遵循单一职责原...
前言
众所周知,react中的组件非常的灵活可扩展,不过随着业务复杂度的增加和许多外部工具库的引入,组件往往也会显得浮肿,接下来我们就一起来看看常见的几种,遵循单一职责原则的,组件分割与解耦的方法,话不多说了,来一起看看详细的介绍:
一、分割 render 函数
当一个组件渲染的内容较多时,有一个快速并且通用的方法是创建sub-render函数来简化原来庞大的 render
class panel extends react.component { renderheading() { // ... } renderbody() { // ... } render() { return ( <div> {this.renderheading()} {this.renderbody()} </div> ); } }
为了再次简化sub-render函数,我们还可以采用functional components写法,这种方式生成了更小的处理单元,且更有利于测试
const panelheader = (props) => ( // ... ); const panelbody = (props) => ( // ... ); class panel extends react.component { render() { return ( <div> // nice and explicit about which props are used <panelheader title={this.props.title}/> <panelbody content={this.props.content}/> </div> ); } }
二、用 props 传递元素
如果一个组件的状态或配置较多,我们可以运用props传递元素而不仅是数据,比如再声明一个组件,使其中的父组件只专注于配置
class commenttemplate extends react.component { static proptypes = { // declare slots as type node metadata: proptypes.node, actions: proptypes.node, }; render() { return ( <div> <commentheading> <avatar user={...}/> // slot for metadata <span>{this.props.metadata}</span> </commentheading> <commentbody/> <commentfooter> <timestamp time={...}/> // slot for actions <span>{this.props.actions}</span> </commentfooter> </div> ); } }
父组件
class comment extends react.component { render() { const metadata = this.props.publishtime ? <publishtime time={this.props.publishtime} /> : <span>saving...</span>; const actions = []; if (this.props.issignedin) { actions.push(<likeaction />); actions.push(<replyaction />); } if (this.props.isauthor) { actions.push(<deleteaction />); } return <commenttemplate metadata={metadata} actions={actions} />; } }
三、使用高阶组件
实现点击某组件的超链接,发送该组件的 id,我们大多的解决方法可能如下
class document extends react.component { componentdidmount() { reactdom.finddomnode(this).addeventlistener('click', this.onclick); } componentwillunmount() { reactdom.finddomnode(this).removeeventlistener('click', this.onclick); } onclick = (e) => { if (e.target.tagname === 'a') { // naive check for <a> elements sendanalytics('link clicked', { documentid: this.props.documentid // specific information to be sent }); } }; render() { // ... } }
然而它却存在代码不能复用,组件重构困难等问题
我们可以使用高阶组件来解决这些问题,顾名思义,高阶组件就是一个函数,传给它一个组件,它返回一个新的组件
function withlinkanalytics(mappropstodata, wrappedcomponent) { class linkanalyticswrapper extends react.component { componentdidmount() { reactdom.finddomnode(this).addeventlistener('click', this.onclick); } componentwillunmount() { reactdom.finddomnode(this).removeeventlistener('click', this.onclick); } onclick = (e) => { if (e.target.tagname === 'a') { // naive check for <a> elements const data = mappropstodata ? mappropstodata(this.props) : {}; sendanalytics('link clicked', data); } }; render() { // simply render the wrappedcomponent with all props return <wrappedcomponent {...this.props} />; } } return linkanalyticswrapper; }
简化代码如下
class document extends react.component { render() { // ... } } export default withlinkanalytics((props) => ({ documentid: props.documentid }), document);
总结
以上 3 个 react 组件的解耦重构方法都可以直接拿来运用,最开始可能会觉得有点棘手,但是没关系,只要坚持下来,你就会写出更强壮和可复用的代码。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。