<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【React】895- 使用 IOC 解耦 React 組件

          共 4436字,需瀏覽 9分鐘

           ·

          2021-03-14 08:46

          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();
          }
          // ...

          理想的狀態(tài)是:士兵不依賴具體的武器,彈藥庫里有什么武器,就用什么武器。

          在這種情況下,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的思想解耦代碼邏輯。

          接下來我們看看專業(yè)的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

          業(yè)務邏輯的更多依賴都可以通過注入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+篇原創(chuàng)系列匯總

          回復“加群”與大佬們一起交流學習~

          點擊“閱讀原文”查看 100+ 篇原創(chuàng)文章


          瀏覽 64
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  老鸭窝日本天堂中文字幕在线免费观看 | 青草精品视频 | 色五月婷婷婷 | 国产AV无码专区亚洲A∨毛片 | 激情伊人网 |