React 设计艺术:如何精确拆分组件接口,实现接口隔离原则

接口隔离原则

接口隔离原则(Interface Segregation Principle,简称 ISP)也是面向对象设计中的重要原则之一。它的核心思想是,一个类不应该依赖它不需要的接口。在 React 开发中,遵循接口隔离原则可以提高代码的可维护性和可扩展性。

接口隔离原则的要点如下:

  1. 客户端不应该强迫依赖它不需要的接口。

  2. 接口应该小而精炼,不应该设计过多不相关的方法。

  3. 类应该根据实际需求,仅实现相关的接口。

在 React 中,我们可以通过组件的拆分和组合来实现接口隔离。下面我们通过示例代码来说明:

复制代码
// 接口一:用于显示用户名的组件接口
const UserNameDisplay = ({ username }) => {
  return <div>{username}</div>;
};

// 接口二:用于显示用户头像的组件接口
const UserAvatarDisplay = ({ avatarUrl }) => {
  return <img src={avatarUrl} />;
};

// 使用上述两个接口的用户信息组件
const UserInfo = ({ username, avatarUrl }) => {
  return (
    <div>
      <UserNameDisplay username={username} />
      <UserAvatarDisplay avatarUrl={avatarUrl} />
    </div>
  );
};

在上述示例中,我们定义了两个独立的组件接口:UserNameDisplay 和 UserAvatarDisplay。这两个组件各自负责显示用户名和用户头像。最后,我们使用这两个接口的组合来构建一个用户信息组件 UserInfo。

通过将接口拆分成较小、单一的组件,并通过组合的方式将它们组装起来,我们实现了接口的隔离。这样一来,不同的组件在使用时不会依赖不需要的功能,从而提高了代码的可维护性和可扩展性。

除了组件拆分和组合之外,也可以使用 React 的 Hooks 来实现接口隔离。React Hooks 是 React 16.8 新增的特性,它可以在函数组件中使用 React 的特性。通过使用自定义 Hooks,我们可以将相关的功能封装在一个独立的 Hook 中,从而实现接口隔离。

总结起来,React 中的接口隔离原则可以通过组件的拆分和组合,或者使用 Hooks 来实现。在开发过程中,我们应该遵循以下原则:

  1. 组件的接口应该小而精炼,只包含实际需要的功能。

  2. 将功能相关的组件接口拆分成独立的组件,通过组合的方式进行组装。

  3. 使用 Hooks 来封装相关功能,实现接口的隔离。

根据接口隔离原则的说法,客户端不应该依赖它不需要的接口

首先,我们看一下组件实现接口隔离原则的区别:

为了更好的说明 ISP 所针对的问题,来看一个呈现视频列表的组件:

复制代码
type Video = {
  title: string
  duration: number
  coverUrl: string
}

type Props = {
  items: Array<Video>
}

const VideoList = ({ items }) => {
  return (
    <ul>
      {items.map(item => 
        <Thumbnail 
          key={item.title} 
          video={item} 
        />
      )}
    </ul>
  )
}

Thumbnail 组件的实现如下:

复制代码
type Props = {
  video: Video,
};

const Thumbnail = ({ video }: Props) => {
  return <img src={video.coverUrl} />;
};

Thumbnail 组件非常小并且很简单,但它有一个问题:它希望将完整的视频对象作为 props 传入,但是仅有效地使用其属性之一(coverUrl)。

除了视频,我们还需要渲染直播的缩略图,这两种媒体资源会混合在同一个列表中。

下面来定义直播的类型 LiveStream

复制代码
type LiveStream = {
  name: string
  previewUrl: string
}

这是更新后的 VideoList 组件:

复制代码
type Props = {
  items: Array<Video | LiveStream>,
};

const VideoList = ({ items }) => {
  return (
    <ul>
            
      {items.map((item) => {
        if ("coverUrl" in item) {
          return <Thumbnail video={item} />;
        } else {
          // 直播组件,该怎么写?
        }
      })}
          
    </ul>
  );
};

这时就发现一个问题,我们可以轻松的区分视频和直播对象,但是不能将后者传递给Thumbnail组件,因为VideoLiveStream类型不兼容。它们包含了不同的属性来保存缩略图:视频对象调用coverUrl,直播对象调用previewUrl。这就是使组件依赖了比实际更多的props的原因所在。

下面来重构 Thumbnail 组件以确保它仅依赖于它需要的props

复制代码
type Props = {
  coverUrl: string,
};

const Thumbnail = ({ coverUrl }: Props) => {
  return <img src={coverUrl} />;
};

通过这样修改,现在我们可以使用它来渲染视频和直播的对略图:

复制代码
type Props = {
  items: Array<Video | LiveStream>,
};

const VideoList = ({ items }) => {
  return (
    <ul>
            
      {items.map((item) => {
        if ("coverUrl" in item) {
          return <Thumbnail coverUrl={item.coverUrl} />;
        } else {
          return <Thumbnail coverUrl={item.previewUrl} />;
        }
      })}
          
    </ul>
  );
};

当然,这段代码还可以简化一下:

复制代码
type Props = {
  items: Array<Video | LiveStream>,
};

const VideoList = ({ items }) => {
  return (
    <ul>
            
      {items.map((item) => (
        <Thumbnail
          coverUrl={"coverUrl" in item ? item.coverUrl : item.previewUrl}
        />
      ))}
          
    </ul>
  );
};

接口隔离原则主张最小化系统组件之间的依赖关系,使它们的耦合度降低,从而提高可重用性。

遵循接口隔离原则有助于提高代码的可维护性和可扩展性。在实际开发中,我们应该注重代码的设计和组织,提高代码的可读性和可复用性,并避免不必要的依赖关系。同时注重代码的重用和扩展性,从而提高开发效率和代码质量。

参考资料

  • React documentation. Retrieved from React
相关推荐
笔COOL创始人3 分钟前
requestAnimationFrame 动画优化实践指南
前端·javascript·面试
sophie旭6 分钟前
性能监控之首屏性能监控小实践
前端·javascript·性能优化
北辰alk14 分钟前
React Consumer 找不到 Provider 的处理方案
react.js
Amumu1213820 分钟前
React 前端请求
前端·react.js·okhttp
3824278271 小时前
JS表单提交:submit事件的关键技巧与注意事项
前端·javascript·okhttp
interception1 小时前
js逆向之京东原型链补环境h5st
javascript·爬虫·网络爬虫
木土雨成小小测试员1 小时前
Python测试开发之前端二
javascript·python·jquery
全栈小51 小时前
【前端】在JavaScript中,=、==和===是三种不同的操作符,用途和含义完全不同,一起瞧瞧
开发语言·前端·javascript
如果你好1 小时前
Vue createRenderer 自定义渲染器从入门到实战
前端·javascript·vue.js