前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[译] 更可靠的 React 组件:组合及可重用性

[译] 更可靠的 React 组件:组合及可重用性

作者头像
江米小枣
发布2020-06-15 22:21:51
2.8K2
发布2020-06-15 22:21:51
举报
文章被收录于专栏:云前端云前端

原文摘自:https://dmitripavlutin.com/7-architectural-attributes-of-a-reliable-react-component/

I. 组合

一个组合式组件是由更小的特定组件组合而成的

组合(composition)是一种通过将各组件联合在一起以创建更大组件的方式。组合是 React 的核心。

幸好,组合易于理解。把一组小的片段,联合起来,创建一个更大个儿的。

让我们来看看一个更通用的前端应用组合模式。应用由头部的 header、底部的 footer、左侧的 sidebar,还有中部的有效内容联合而成:

<div id="root"></div>
function Application({ children }) {
  return (
    <div className="application box">
      <Label>Application</Label>
      {children}
    </div>
  );
}

function Header() {
  return (
    <div className="header box">
      <Label>Header</Label>
    </div>
  )
}

function Footer() {
  return (
    <div className="header box">
      <Label>Footer</Label>
    </div>
  )
}

function Sidebar({ children }) {
  return (
    <div className="sidebar box">
      <Label>Sidebar</Label>
      {children}
    </div>
  );
}

function Content({ children }) {
  return (
    <div className="content box">
      <Label>Content</Label>
      {children}
    </div>
  )
}

function Menu() {
  return (
    <div className="menu box">
      <Label>Menu</Label>
      <div className="description">
        <div className="text shorter" />
        <div className="text" />
        <div className="text shorter" />
        <div className="text shorter" />
      </div>
    </div>
  );
}

function Article() {
  return (
    <div className="article box">
      <Label>Article</Label>
      <div className="description">
          <div className="text shorter" /> <div className="text longer" />
          <div className="text shorter" /> <div className="text" />
          <div className="text shorter" /> <div className="text" />
          <div className="text" /> <div className="text shorter" />
          <div className="text shorter" /> <div className="text" />
          <div className="text" /> <div className="text shorter" />
          <div className="text shorter" /> <div className="text longer" />
          <div className="text shorter" /> <div className="longer" />
          <div className="text shorter" /> <div className="text" />
          <div className="text" /> <div className="text shorter" />
          <div className="text shorter" /> <div className="text" />
      </div>
    </div>
  );
}

function Label({ children }) {
  return <div className="label">&lt;{children}&gt;</div>
}

const app = (
  <Application>
    <Header />
    <Sidebar>
      <Menu />
    </Sidebar>
    <Content>
      <Article />
    </Content>
    <Footer />
  </Application>
);

ReactDOM.render(app, document.getElementById('root')); 

骨架部分展示了好的组合如何构建应用。这样组织代码即富于表现力又便于理解。

React 组件的组合是自然而然的。这个库使用了一个描述式的范式,从而不会抑制组合式的表现力。

<Application><Header><Sidebar><Content><Footer> 组合而成。 <Sidebar> 只有一个子组件 <Menu>,而 <Content> 同样也只有 <Article>

那么组合式和单一职责以及封装有何联系呢?让我们来看看:

单一职责原则(SRP) 描述了如何根据需求划分组件,封装(encapsulation) 则描述了如何组织这些组件,而 组合(composition) 描述的是如何把整个系统粘合在一起。

单一职责

组合的一个重要方面在于从特定的小组件组成复杂组件的能力。这种逐个击破(divide and conquer)的方式帮助了被组合而成的复杂组件也能符合 SRP 原则。

回顾之前的代码片段,<Application> 的职责就是渲染 header、footer、sidebar 和主体区域。要明白的是这个职责被分割为了四个子职责,每个子职责由对应的子组件实现。

也就是说,组合的好处在于,通过允许子组件分别实现单一职责的方式,让 <Application> 这样的组件也符合了单一职责原则。

可重用性

使用组合的组件也有可重用性的优点,可以重用通用的逻辑。

举例来说,<Composed1><Composed2> 共享了通用的逻辑:

const instance1 = (  
 <Composed1>
   /* Composed1 组件的特定代码... */
   /* 通用代码... */
 </Composed1>
);
const instance2 = (  
 <Composed2>
   /* 通用代码... */
   /* Composed2 组件的特定代码... */
 </Composed2>
);

既然 ctrl+C/ctrl+V 人人喊打,那如何让组件重用通用逻辑呢?

首先,将通用代码封装到新组件 <Common> 中。其次,<Composed1><Composed2> 应使用组合方式来包含 <Common>;代码实现如下:

const instance1 = (  
 <Composed1>
   <Piece1 />
   <Common />
 </Composed1>
);
const instance2 = (  
 <Composed2>
   <Common />
   <Piece2 />
 </Composed2>
);

可重用的组件符合 Don't repeat yourself (DRY) 原则。这种有益的实践节省了时间和精力。

灵活性

在 React 中一个组合式的组件可以控制其子组件,这通常是通过 children 属性实现的。这带来了另一个好处 -- 灵活性

比如,有一个组件根据用户设备显示提示信息。使用组合可以灵活地实现这个需求:

function ByDevice({ children: { mobile, other } }) {  
  return Utils.isMobile() ? mobile : other;
}

<ByDevice>{{  
  mobile: <div>检测到移动设备!</div>,
  other:  <div>非移动设备</div>
}}</ByDevice>

有效性

用户界面就是组合式的分层结构。这种组件的组合是一种构建 UI 的有效的方式。

II. 可重用性

一个可重用的组件,可以做到一次编写多次使用

想象一下,如果有那么一个总是重复发明轮子的软件开发世界。

人们编写代码时,不能使用任何已有库或工具。甚至在同一个应用中你都不能使用写过的任何代码。

在这种环境中,是否有可能在合理的时间内编写出一个应用呢?绝无可能。

有请可重用性出场 -- 让事情运转起来,而非重新发明如何让其运作。

应用内的重用

根据 Don't repeat yourself (DRY) 原则,知识的每一个片段在系统中都应该是单独、不含糊而权威的。DRY 原则就是为了避免重复。

代码重复提高了复杂性和维护成本,却没有带来显著的价值。一处逻辑的更新会迫使你修改应用中其所有重复的副本。

重复问题要靠可重用的组件来解决。编写一次使用多次,是一种有效而省时的策略。

但享受可重用性也非毫无成本的。必须符合单一职责原则和合理的封装,才能说组件是可重用的。

符合单一职责原则是必须的:

重用一个组件实际上就意味着重用其职责

所以,只有唯一职责的组件最容易被重用。

当组件不恰当的具有了多个职责时,其可重用性就收到了很大的限制。只想重用某一个职责时,又会面对由其余不需要的实现造成的职责。

想要一个香蕉,香蕉倒是拿到了 -- 整个丛林都跟了过来。

合理的封装的组件不会被依赖卡住。隐藏的内部结构以及目的明确的 props ,使得组件可以良好的适用于重用其的多个场合。

重用第三方库

今天天气不错还风和日丽哒,你打开电脑,并在启动编辑器的几分钟里,看了看今天的需求 -- 往应用里添加一个新特性,准备开干了...

然而此时你要做的事情在很大概率上实际上是已经被解决过的了。由于 React 的流行度以及其非常棒的开源社区,所以先搜索一下是否有已存在的解决方案是明智的。

检出 brillout/awesome-react-components 仓库,会发现一个编辑过的可重用组件菜单。

良好的库无疑会产生结构性的影响并推广最佳实践。以我的经验而言,最有影响的当属 react-router 和 redux。

react-router 使用了声明式的路由来规划一个单页应用的结构。使用 <Route> 可以将一个 URL 和一个组件联系起来。而后当用户访问匹配的 URL 时,路由将渲染相应的组件。

reduxreact-redux 引入了单向且可预期的应用状态管理。借助它们,可以将异步的和非纯的代码(例如 HTTP 请求)从组件中提取出来,从而符合单一职责原则并创建出 纯(pure)组件几乎纯(almost-pure)的组件

要确定第三方库是否堪用,这里是一份检查清单:

  • 文档:检查库是否具备有意义的 README.md 文件以及详细的文档
  • 测试过的:可信赖库的一个显著特征就是有高的代码覆盖率
  • 维护:看看库作者创建新特性、修改bug及日常维护的频率如何
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-06-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • I. 组合
    • 单一职责
      • 可重用性
        • 灵活性
          • 有效性
          • II. 可重用性
            • 应用内的重用
              • 重用第三方库
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档