详解使用IOC解耦React组件

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

[[386478]]

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

本文包括两部分:

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

IOC是什么

让我们来看个例子:

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

  1. class Soldier { 
  2.   constructor() { 
  3.     // 这里我们实例化一把步枪 
  4.     this.weapon = new Rifle(); 
  5.   } 
  6.   attack() { 
  7.     this.weapon.attack(); 
  8.   } 

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

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

  1. // ... 
  2. constructor() { 
  3.   // 这里我们实例化一把步枪 
  4.   // this.weapon = new Rifle(); 
  5.   // 这里我们实例化一个手榴弹 
  6.   this.weapon = new Grenade(); 
  7. // ... 

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

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

让我们来改写代码:

第一步:DI(Dependency Injection)

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

  1. class Soldier { 
  2.   // 将武器作为依赖注入 
  3.   constructor(weapon) { 
  4.     this.weapon = weapon; 
  5.   } 
  6.   attack() { 
  7.     this.weapon.attack(); 
  8.   } 

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

  1. const s1 = new Soldier(new Rifle()); 
  2. const s2 = new Soldier(new Grenade()); 

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

第二步:IOC容器

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

  1. class Armory { 
  2.   constructor() { 
  3.     this.weapon = null
  4.   } 
  5.   setWeapon(weapon) { 
  6.     this.weapon = weapon; 
  7.   } 
  8.   getWeapon() { 
  9.     return this.weapon; 
  10.   } 

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

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

  1. const armory1 = new Armory(); 
  2.  
  3. class Soldier { 
  4.   // 将武器作为依赖注入 
  5.   constructor(armory) { 
  6.     this.weapon = armory.getWeapon(); 
  7.   } 
  8.   attack() { 
  9.     this.weapon.attack(); 
  10.   } 

改造前的依赖关系:

  1. 士兵 --> 武器 

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

改造后的依赖关系:

  1. 士兵 --> 武器库 <-- 武器 

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

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

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

IOC与React

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

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

  1. function Name() { 
  2.   const {name} = useContext(nameContext); 
  3.   reutrn <h1>{name}</h1>; 

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

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

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

InversifyJS

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


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

  1. // armory.ts 
  2. import { injectable } from "inversify"
  3.  
  4. export interface IArmory<T> { 
  5.   attack(): T; 
  6.  
  7. @injectable() 
  8. export class Armory implements IArmory<string> { 
  9.   attack() { 
  10.     return "Rifle biubiubiu~"
  11.   } 

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

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

  1. import React from "react"
  2. import { IArmory } from "./armory"
  3.  
  4. export class Soldier extends React.Component { 
  5.   private readonly Armory: IArmory<string>; 
  6.  
  7.   render() { 
  8.     return <h1 onClick={() => this.armory.attack()}>I am a soldier</h1>; 
  9.   } 

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

  1. import { Container } from "inversify"
  2. import { IArmory, Armory } from "./armory"
  3.  
  4. // 实例化IOC容器 
  5. export const container = new Container(); 
  6. // 将依赖方注入容器,其中armory为该依赖的ID 
  7. 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

 

责任编辑:姜华 来源: 魔术师卡颂
相关推荐

2020-10-16 18:41:43

command设计模式代码

2022-09-02 08:23:12

软件开发解耦架构

2013-09-16 10:19:08

htmlcssJavaScript

2016-11-30 15:30:42

架构工具和方案

2020-11-20 15:22:32

架构运维技术

2024-03-08 16:27:22

领域事件DDD项目跨层解耦

2022-04-15 11:46:09

轻量系统解耦鸿蒙操作系统

2018-04-18 08:47:17

Alluxio构建存储

2017-03-21 21:37:06

组件UI测试架构

2023-06-05 07:52:28

召回模型推荐系统

2017-12-26 15:52:31

MQ互联网耦合

2022-12-28 07:45:17

2022-06-07 07:58:16

流程解耦封装

2017-11-15 09:32:27

解耦战术架构

2022-07-18 09:01:58

React函数组件Hooks

2010-02-03 15:59:08

Android组件

2021-06-01 09:38:19

消息队列核心系统下游系统

2018-01-01 06:41:44

耦合互联网架构配置中心

2012-07-10 01:47:14

代码架构设计

2022-08-10 06:52:28

RabbitMQ消息中间件
点赞
收藏

51CTO技术栈公众号