前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用IOC解耦React组件

使用IOC解耦React组件

作者头像
公众号@魔术师卡颂
发布2021-03-15 16:16:43
8960
发布2021-03-15 16:16:43
举报
文章被收录于专栏:魔术师卡颂

IOC(控制反转)是一种编程思想,可以解耦组件,提高组件复用性。

本文包括两部分:

  1. 介绍IOC概念
  2. IOCReact中的应用

IOC是什么

让我们来看个例子:

我们有个士兵的类,在类内部会实例化一种武器:

代码语言:javascript
复制
class Soldier {
  constructor() {
    // 这里我们实例化一把步枪
    this.weapon = new Rifle();
  }
  attack() {
    this.weapon.attack();
  }
}

士兵的武器应该是多种多样的,但是在Soldier类内部依赖了Rifle

所以当我们想将武器从步枪换为手榴弹时,只能这样改写:

代码语言:javascript
复制
// ...
constructor() {
  // 这里我们实例化一把步枪
  // this.weapon = new Rifle();
  // 这里我们实例化一个手榴弹
  this.weapon = new Grenade();
}
// ...

理想的状态是:士兵不依赖具体的武器,弹药库里有什么武器,就用什么武器。

在这种情况下,IOC作为弹药库,就派上了用场。

让我们来改写代码:

第一步:DI(Dependency Injection)

改写的第一步是使士兵不依赖具体的武器,而是将武器作为依赖注入给士兵:

代码语言:javascript
复制
class Soldier {
  // 将武器作为依赖注入
  constructor(weapon) {
    this.weapon = weapon;
  }
  attack() {
    this.weapon.attack();
  }
}

我们将武器的实例作为Soldier的参数传入,于是可以如下调用:

代码语言:javascript
复制
const s1 = new Soldier(new Rifle());
const s2 = new Soldier(new Grenade());

这一步被称为DI(依赖注入)。

第二步:IOC容器

那么武器从哪儿来呢?接下来来打造我们的武器库:

代码语言:javascript
复制
class Armory {
  constructor() {
    this.weapon = null;
  }
  setWeapon(weapon) {
    this.weapon = weapon;
  }
  getWeapon() {
    return this.weapon;
  }
}

武器库支持存武器(setWeapon)和取武器(getWeapon)。

现在,士兵不依赖具体武器,只需要去武器库取武器:

代码语言:javascript
复制

const armory1 = new Armory();

class Soldier {
  // 将武器作为依赖注入
  constructor(armory) {
    this.weapon = armory.getWeapon();
  }
  attack() {
    this.weapon.attack();
  }
}

改造前的依赖关系:

代码语言:javascript
复制
士兵 --> 武器

改造前原先应用(士兵)拥有依赖的完全控制权。

改造后的依赖关系:

代码语言:javascript
复制
士兵 --> 武器库 <-- 武器

改造后应用(士兵)与服务提供方(武器)解耦,他们通过IOC容器(武器库)联系。

Demo也能看出IOCDI的关系:DI是实现IOC编程思想的一种方式。

除了DI外,另一种实现方式是Dependency Lookup(依赖查找),简称DL

IOC与React

React中,为组件传递的props就是一种DI实现。

为了跨层级传递数据,我们常使用Context API

代码语言:javascript
复制
function Name() {
  const {name} = useContext(nameContext);
  reutrn <h1>{name}</h1>;
}

context将依赖提供方(name)与依赖使用方(Name)隔离,可以看作是一种IOC实现。

所以说,合理使用React可以充分利用IOC的思想解耦代码逻辑。

接下来我们看看专业的DI库如何与React结合:

InversifyJS

InversifyJS[1]是一个强大、轻量的DI库。

首先我们实现依赖(武器的实现):

代码语言:javascript
复制
// armory.ts
import { injectable } from "inversify";

export interface IArmory<T> {
  attack(): T;
}

@injectable()
export class Armory implements IArmory<string> {
  attack() {
    return "Rifle biubiubiu~";
  }
}

通过inversify提供的injectable decorator标记该class是可被注入的。

接下来实现需求方(士兵的实现):

代码语言:javascript
复制
import React from "react";
import { IArmory } from "./armory";

export class Soldier extends React.Component {
  private readonly Armory: IArmory<string>;

  render() {
    return <h1 onClick={() => this.armory.attack()}>I am a soldier</h1>;
  }
}

最后实例化IOC容器,连接需求方与依赖:

代码语言:javascript
复制

import { Container } from "inversify";
import { IArmory, Armory } from "./armory";

// 实例化IOC容器
export const container = new Container();
// 将依赖方注入容器,其中armory为该依赖的ID
container.bind<IArmory<string>>("armory").to(Armory);

至此,完成一个React组件的简单IOC

业务逻辑的更多依赖都可以通过注入IOC容器来实现解耦。

Hooks同样可以通过inversify完成IOC,参考Dependency injection in React using InversifyJS. Now with React Hooks[2]

参考资料

[1]

InversifyJS: https://github.com/inversify/InversifyJS

[2]

Dependency injection in React using InversifyJS. Now with React Hooks: https://itnext.io/dependency-injection-in-react-using-inversifyjs-now-with-react-hooks-64f7f077cde6

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 魔术师卡颂 微信公众号,前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • IOC是什么
    • 第一步:DI(Dependency Injection)
      • 第二步:IOC容器
      • IOC与React
      • InversifyJS
        • 参考资料
        相关产品与服务
        容器服务
        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档