0

0

分解React组件的几种进阶方法

小云云

小云云

发布时间:2018-02-09 16:40:36

|

2418人浏览过

|

来源于php中文网

原创

react 组件魔力无穷,同时灵活性超强。我们可以在组件的设计上,玩转出很多花样。但是保证组件的single responsibility principle: 单一原则非常重要,它可以使得我们的组件更简单、更方便维护,更重要的是使得组件更加具有复用性。本文主要和大家分享分解react 组件的几种进阶方法,希望能帮助到大家。

但是,如何对一个功能复杂且臃肿的 React 组件进行分解,也许并不是一件简单的事情。本文由浅入深,介绍三个分解 React 组件的方法。

方法一:切割 render() 方法

这是一个最容易想到的方法:当一个组件渲染了很多元素时,就需要尝试分离这些元素的渲染逻辑。最迅速的方式就是切割 render() 方法为多个 sub-render 方法。

看下面的例子会更加直观:

class Panel extends React.Component {
    renderHeading() {        // ...
    }

    renderBody() {        // ...
    }

    render() {        return (
            
{this.renderHeading()} {this.renderBody()}
); } }

细心的读者很快就能发现,其实这并没有分解组件本身,该 Panel 组件仍然保持有原先的 state, props, 以及 class 方法。

如何真正地做到减少组件复杂度呢?我们需要创建一些子组件。此时,采用最新版 React 支持并推荐的函数式组件/无状态组件一定会是一个很好的尝试:

const PanelHeader = (props) => (    // ...);const PanelBody = (props) => (    // ...);class Panel extends React.Component {
    render() {        return (
            
// Nice and explicit about which props are used
); } }

同之前的方式相比,这个微妙的改进是革命性的。

我们新建了两个单元组件:PanelHeader 和 PanelBody。这样带来了测试的便利,我们可以直接分离测试不同的组件。同时,借助于 React 新的算法引擎 React Fiber,两个单元组件在渲染的效率上,乐观地预计会有较大幅度的提升。

方法二:模版化组件

回到问题的起点,为什么一个组件会变的臃肿而复杂呢?其一是渲染元素较多且嵌套,另外就是组件内部变化较多,或者存在多种 configurations 的情况。

此时,我们便可以将组件改造为模版:父组件类似一个模版,只专注于各种 configurations。

还是要举例来说,这样理解起来更加清晰。

比如我们有一个 Comment 组件,这个组件存在多种行为或事件。

同时组件所展现的信息根据用户的身份不同而有所变化:

  • 用户是否是此 comment 的作者;

  • 此 comment 是否被正确保存;

  • 各种权限不同

  • 等等......

都会引起这个组件的不同展示行为。

这时候,与其把所有的逻辑混淆在一起,也许更好的做法是利用 React 可以传递 React element 的特性,我们将 React element 进行组件间传递,这样就更加像一个强大的模版:

class CommentTemplate extends React.Component {
    static propTypes = {        // Declare slots as type node
        metadata: PropTypes.node,
        actions: PropTypes.node,
    };

    render() {        return (            
// Slot for metadata {this.props.metadata} // Slot for actions {this.props.actions}
... ) } }

此时,我们真正的 Comment 组件组织为:

class Comment extends React.Component {
    render() {        const metadata = this.props.publishTime ?         :        Saving...;        const actions = [];        if (this.props.isSignedIn) {
            actions.push();
            actions.push();
        }
        if (this.props.isAuthor) {
            actions.push();
        }

        return ;
    }
}

metadata 和 actions 其实就是在特定情况下需要渲染的 React element。

比如:

  • 如果 this.props.publishTime 存在,metadata 就是

    站长俱乐部购物系统
    站长俱乐部购物系统

    功能介绍:1、模块化的程序设计,使得前台页面设计与程序设计几乎完全分离。在前台页面采用过程调用方法。在修改页面设计时只需要在相应位置调用设计好的过程就可以了。另外,这些过程还提供了不同的调用参数,以实现不同的效果;2、阅读等级功能,可以加密产品,进行收费管理;3、可以完全可视化编辑文章内容,所见即所得;4、无组件上传文件,服务器无需安装任何上传组件,无需支持FSO,即可上传文件。可限制文件上传的类

    下载
  • 反之则为 Saving...

  • 如果用户已经登陆,则需要渲染(即actions值为)

  • 如果是作者本身,需要渲染的内容就要加入

方法三:高阶组件

在实际开发当中,组件经常会被其他需求所污染。

想象这样一个场景:我们想统计页面中所有链接的点击信息。在链接点击时,发送统计请求,同时这条请求需要包含此页面 document 的 id 值。

常见的做法是在 Document 组件的生命周期函数 componentDidMount 和 componentWillUnmount 增加代码逻辑:

class Document extends React.Component {
    componentDidMount() {
        ReactDOM.findDOMNode(this).addEventListener('click', this.onClick);
    }

    componentWillUnmount() {
        ReactDOM.findDOMNode(this).removeEventListener('click', this.onClick);
    }

    onClick = (e) => {        // Naive check for  elements        if (e.target.tagName === 'A') { 
            sendAnalytics('link clicked', {                // Specific information to be sent
                documentId: this.props.documentId 
            });
        }
    };

    render() {        // ...
    }
}

这么做的几个问题在于:

  • 相关组件 Document 除了自身的主要逻辑:显示主页面之外,多了其他统计逻辑;

  • 如果 Document 组件的生命周期函数中,还存在其他逻辑,那么这个组件就会变的更加含糊不合理;

  • 统计逻辑代码无法复用;

  • 组件重构、维护都会变的更加困难。

为了解决这个问题,我们提出了高阶组件这个概念: higher-order components (HOCs)。不去晦涩地解释这个名词,我们来直接看看使用高阶组件如何来重构上面的代码:

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) => {            // Naive check for  elements            if (e.target.tagName === 'A') { 
                const data = mapPropsToData ? mapPropsToData(this.props) : {};
                sendAnalytics('link clicked', data);
            }
        };

        render() {            // Simply render the WrappedComponent with all props            return ;
        }
    }
    ...
}

需要注意的是,withLinkAnalytics 函数并不会去改变 WrappedComponent 组件本身,更不会去改变 WrappedComponent 组件的行为。而是返回了一个被包裹的新组件。实际用法为:

class Document extends React.Component {
    render() {        // ...
    }
}

export default withLinkAnalytics((props) => ({
    documentId: props.documentId
}), Document);

这样一来,Document 组件仍然只需关心自己该关心的部分,而 withLinkAnalytics 赋予了复用统计逻辑的能力。

高阶组件的存在,完美展示了 React 天生的复合(compositional)能力,在 React 社区当中,react-redux,styled-components,react-intl 等都普遍采用了这个方式。值得一提的是,recompose 类库又利用高阶组件,并发扬光大,做到了“脑洞大开”的事情。

React 及其周边社区的崛起,让函数式编程风靡一时,受到追捧。其中关于 decomposing 和 composing 的思想,我认为非常值得学习。同时,对开发设计的一个建议是,一般情况下,不要犹豫将你的组件拆分的更小、更单一,因为这样能换来强健和复用。

相关推荐:

React组件生命周期实例分析

构建React组件最全方法

store优化React组件的方法详解

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

12

2026.01.30

python 字符串格式化
python 字符串格式化

本专题整合了python字符串格式化教程、实践、方法、进阶等等相关内容,阅读专题下面的文章了解更多详细操作。

4

2026.01.30

java入门学习合集
java入门学习合集

本专题整合了java入门学习指南、初学者项目实战、入门到精通等等内容,阅读专题下面的文章了解更多详细学习方法。

20

2026.01.29

java配置环境变量教程合集
java配置环境变量教程合集

本专题整合了java配置环境变量设置、步骤、安装jdk、避免冲突等等相关内容,阅读专题下面的文章了解更多详细操作。

18

2026.01.29

java成品学习网站推荐大全
java成品学习网站推荐大全

本专题整合了java成品网站、在线成品网站源码、源码入口等等相关内容,阅读专题下面的文章了解更多详细推荐内容。

19

2026.01.29

Java字符串处理使用教程合集
Java字符串处理使用教程合集

本专题整合了Java字符串截取、处理、使用、实战等等教程内容,阅读专题下面的文章了解详细操作教程。

3

2026.01.29

Java空对象相关教程合集
Java空对象相关教程合集

本专题整合了Java空对象相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.4万人学习

国外Web开发全栈课程全集
国外Web开发全栈课程全集

共12课时 | 1.0万人学习

React核心原理新老生命周期精讲
React核心原理新老生命周期精讲

共12课时 | 1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号