应用开发

详解使用IOC解耦React组件

时间:2010-12-5 17:23:32  作者:数据库   来源:数据库  查看:  评论:0
内容摘要:IOC(控制反转)是一种编程思想,可以解耦组件,提高组件复用性。本文包括两部分:介绍IOC概念 IOC在React中的应用 IOC是什么让我们来看个例子:我们有个士兵的类,

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

本文包括两部分:

介绍IOC概念 IOC在React中的详解应用

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也能看出IOC与DI的关系: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

copyright © 2025 powered by 益强资讯全景  滇ICP备2023006006号-31sitemap