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

本文包括两部分:

  1. 介绍IOC概念

  2. IOCReact中的应用

IOC是什么

让我们来看个例子:

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

class Soldier {constructor() {// 这里我们实例化一把步枪this.weapon = new Rifle();}attack() {this.weapon.attack();}
}

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

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

// ...
constructor() {// 这里我们实例化一把步枪// this.weapon = new Rifle();// 这里我们实例化一个手榴弹this.weapon = new Grenade();
}
// ...

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

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

让我们来改写代码:

第一步:DI(Dependency Injection)

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

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

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

const s1 = new Soldier(new Rifle());
const s2 = new Soldier(new Grenade());

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

第二步:IOC容器

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

class Armory {constructor() {this.weapon = null;}setWeapon(weapon) {this.weapon = weapon;}getWeapon() {return this.weapon;}
}

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

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


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

改造前的依赖关系:

士兵 --> 武器

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

改造后的依赖关系:

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

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

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

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

IOC与React

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

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

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

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

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

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

InversifyJS

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

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

// 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是可被注入的。

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

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容器,连接需求方与依赖:


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

1. JavaScript 重温系列(22篇全)

2. ECMAScript 重温系列(10篇全)

3. JavaScript设计模式 重温系列(9篇全)

4. 正则 / 框架 / 算法等 重温系列(16篇全)

5. Webpack4 入门(上)|| Webpack4 入门(下)

6. MobX 入门(上) ||  MobX 入门(下)

7. 100+篇原创系列汇总

回复“加群”与大佬们一起交流学习~

点击“阅读原文”查看 100+ 篇原创文章

【React】895- 使用 IOC 解耦 React 组件相关推荐

  1. React 中动态的加载组件 ---loadable-components

    loadable-components 用于在react 中动态的加载组件 安装方法: npm i loadable-components 使用: 引入: 代码中使用: 希望对你有所帮助

  2. React学习:ref调用、组件封装调用-学习笔记

    文章目录 React学习:ref调用.组件封装调用-学习笔记 ref调用-string形式 ref调用-回调形式(官方推荐) ref调用-父调子 组件封装调用demo(全选) demo1(单组件) d ...

  3. React(二):类组件、函数式组件

    Component(组件)可以是类组件(class component).函数式组件(function component). 1.类组件: 通常情况下,我们会使用ES6的class关键字来创建Rea ...

  4. React文档(五)组件和props

    组件可以让你将UI分割成独立的,可复用的模块,然后考虑将每个模块彼此隔离. 从概念上理解,组件就像js中的函数.他们接受随意的输入(被称为props)然后返回React元素来描述屏幕上应该出现什么. ...

  5. [react] 说说你对“在react中,一切都是组件”的理解

    [react] 说说你对"在react中,一切都是组件"的理解 React采用组件化的思想,最小的组件单位就是原生HTML元素,采用JSX的语法声明组件的调用 React的虚拟DO ...

  6. [react] 你是如何划分React组件的?

    [react] 你是如何划分React组件的? 可复用的功能 可复用的页面 当你在多个地方写一样或类似的代码时,就该考虑封装组件 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚持 ...

  7. [react] 怎样有条件地渲染组件?

    [react] 怎样有条件地渲染组件? {condition && <Component />} or {condition ? <Component /> : ...

  8. [react] 你有使用过loadable组件吗?它帮我们解决了什么问题?

    [react] 你有使用过loadable组件吗?它帮我们解决了什么问题? 目前有两个 react-loadable和 loadable component,用于代码分割,解决打包体积过大的问题 个人 ...

  9. React Native使用指南-原生UI组件

    在如今的App中,已经有成千上万的原生UI部件了--其中的一些是平台的一部分,另一些可能来自于一些第三方库,而且可能你自己还收藏了很多.React Native已经封装了大部分最常见的组件,譬如Scr ...

最新文章

  1. 《构建高可用Linux服务器》第一版勘误表(附脚本下载)
  2. jQuery 实战读书笔记之第四章:使用特性、属性和数据
  3. mysql ansi_ANSI模式下如何运行MySQL
  4. 利用线性链表基本操作完成两个有序线性表的合并
  5. Mysql group by 问题
  6. Ubuntu16.04安装Caffe(CPU Only)
  7. 使用ASP.NET Atlas实现拖放(Drag Drop)效果(下)
  8. vuex中actions配合mutation处理axios请求
  9. 你是否还在写try-catch-finally?来使用try-with-resources优雅地关闭流吧
  10. iphone新旧手机数据传输已取消_iPhone 手机支付宝自动扣费?取消服务提示“无法解约”?...
  11. 【项目管理】启动 - 项目启动会议
  12. javaweb网上购物系统,jsp网页线上购物,mysql(源码+报告)
  13. 自定义数据集算子数据结构
  14. python下载CVF论文
  15. JS简单入门学习笔记一
  16. 大数据可视化陈为智慧树_知到智慧树大数据可视化网课答案
  17. android仿IT之家、炫酷水波纹、Kotlin MVP项目、后台模拟点击、蜂巢迷宫小游戏等源码
  18. 如何将大量图片文件合并成一个*.bin文件
  19. 如何知道计算机显示器尺寸,电脑显示器尺寸怎么看(电脑显示器常见参数详解)...
  20. shiro设置ip白名单_亚马逊家庭IP:Luminati的搭建的步骤

热门文章

  1. 依据Spring Boot学习视频写的笔记
  2. POJ1011-Sticks
  3. 3dsmax制作一个机器人
  4. 投资110亿元!美的新能源汽车零部件新基地安庆开工;英飞凌投资20亿欧元扩大产能 | 美通社头条...
  5. 电池mAh代表什么?
  6. vb6设置打印机纸张类型,以及打印方向
  7. fixup或parse_tags物理内存解析 - linux内存管理(四)
  8. jQuery选择器重点总结
  9. centos 8.2 指南
  10. 【转】Android 手机连接台式电脑无线 Wi-Fi 上网