成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

React中的依賴注入,看這一篇就夠了!

開(kāi)發(fā) 前端
在 React 中,依賴注入可以通過(guò)將服務(wù)作為 props 注入或使用容器通過(guò)鉤子為組件提供依賴關(guān)系來(lái)實(shí)現(xiàn)。 這種做法可以使代碼更清晰、更易于維護(hù),從而更容易重用業(yè)務(wù)邏輯和管理依賴項(xiàng)。

React 組件不應(yīng)該包含業(yè)務(wù)邏輯,你同意嗎? 如果是,請(qǐng)繼續(xù)閱讀。 如果沒(méi)有,請(qǐng)立即停止。 這篇文章是寫(xiě)給別人的。

只需 3 個(gè)步驟即可將依賴注入添加到您的 React 項(xiàng)目中:

創(chuàng)建一個(gè)“容器”來(lái)放置您的依賴項(xiàng)

創(chuàng)建一個(gè)鉤子 useInject 來(lái)檢索依賴項(xiàng)

使用組件中的鉤子

長(zhǎng)版

如果您對(duì)答案持觀望態(tài)度,我將嘗試為您提供一些關(guān)于為什么我們不應(yīng)該這樣做的見(jiàn)解:

React 是一個(gè)用于創(chuàng)建用戶界面的庫(kù); 這個(gè)定義應(yīng)該阻止我們將業(yè)務(wù)邏輯放入組件中。

包含業(yè)務(wù)邏輯的組件很難閱讀、維護(hù)和測(cè)試。

從組件中提取業(yè)務(wù)邏輯是一個(gè)能夠重用它的好主意。

好的,如果我們從組件中取出業(yè)務(wù)邏輯,我們應(yīng)該將其編寫(xiě)在某個(gè)地方,例如外部類或函數(shù)中。 我們?cè)撛趺醋瞿兀?通過(guò)使用依賴注入!

什么是依賴注入,為什么要使用它

依賴注入 (DI) 是一種軟件設(shè)計(jì)模式,它將對(duì)象的創(chuàng)建與其使用分開(kāi)。 實(shí)際上,對(duì)象的實(shí)例化不是在使用它們的代碼中創(chuàng)建事物,而是委托給負(fù)責(zé)創(chuàng)建對(duì)象并將其提供給需要它們的組件的外部實(shí)體。

依賴注入旨在使代碼更加靈活、模塊化且易于測(cè)試。 DI 不是嚴(yán)格的、緊密耦合的代碼,而是允許模塊化組件輕松替換或擴(kuò)展,而無(wú)需更改使用它們的代碼。

此外,DI 有助于提高代碼的可讀性和可維護(hù)性,因?yàn)樗菇M件之間的依賴關(guān)系變得明確,并有利于復(fù)雜依賴關(guān)系的管理。

總之,依賴注入的作用是:

將對(duì)象的創(chuàng)建與其使用分開(kāi)

使代碼更加靈活、模塊化且易于測(cè)試

提高代碼的可讀性和可維護(hù)性。

React 中的依賴注入

假設(shè)我們需要開(kāi)發(fā)一個(gè)管理待辦事項(xiàng)列表的 React 應(yīng)用程序(多么奇特)。

我們將有一個(gè)顯示待辦事項(xiàng)列表的組件。我們希望在渲染組件時(shí)從某些 API 加載列表。 由于我們不想在組件中編寫(xiě)業(yè)務(wù)邏輯,因此我們將擁有一個(gè)執(zhí)行 API 調(diào)用的服務(wù),我們可以在組件中使用該服務(wù)。 如該圖所示。

在此序列圖中,組件通過(guò)調(diào)用方法或函數(shù)向服務(wù)發(fā)送數(shù)據(jù)請(qǐng)求。 然后,服務(wù)通過(guò)發(fā)送請(qǐng)求從外部 API 檢索數(shù)據(jù)。 一旦接收到數(shù)據(jù),服務(wù)就會(huì)對(duì)其進(jìn)行處理并將其返回給組件。

事件的順序由圖中的箭頭指示。 從API到Service的虛線箭頭表示從API檢索數(shù)據(jù),而從Service到Component的實(shí)線箭頭表示將處理后的數(shù)據(jù)返回到Component。

在實(shí)現(xiàn)級(jí)別,代碼可能如下所示:

import React, { useState, useEffect } from 'react';
import TodoService from './TodoService';

function TodoList() {
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    async function fetchTodos() {
      try {
        const todos = await TodoService.getTodos(); // Call TodoService to get todos
        setTodos(todos);
      } catch (error) {
        console.error(error);
      }
    }
    fetchTodos();
  }, []);

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

export default TodoList;

在此代碼中,我們定義了一個(gè) TodoList 組件,該組件從 TodoService 調(diào)用 getTodos 方法。 我們使用 useState 掛鉤來(lái)跟蹤從服務(wù)返回的待辦事項(xiàng),并使用 useEffect 掛鉤在組件安裝時(shí)獲取待辦事項(xiàng)。

當(dāng) fetchTodos 函數(shù)被調(diào)用時(shí),它使用await關(guān)鍵字等待getTodos方法返回todos。 一旦待辦事項(xiàng)返回并使用 setTodos 函數(shù)將其設(shè)置為待辦事項(xiàng)狀態(tài)變量。

最后,我們使用地圖函數(shù)渲染待辦事項(xiàng)列表并顯示每個(gè)待辦事項(xiàng)的標(biāo)題。 請(qǐng)注意,這是一個(gè)簡(jiǎn)化的示例,TodoService 的實(shí)現(xiàn)可能會(huì)根據(jù)所使用的 API 的不同而有所不同。

使用 props 進(jìn)行依賴注入

import React, { useState, useEffect } from 'react';

function TodoList({ todoService }) {
  const [todos, setTodos] = useState([]);

  useEffect(() => {
    async function fetchTodos() {
      try {
        const todos = await todoService.getTodos(); // Call injected TodoService to get todos
        setTodos(todos);
      } catch (error) {
        console.error(error);
      }
    }
    fetchTodos();
  }, [todoService]);

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}

export default TodoList;

在此更新的代碼中,我們將 TodoService 作為 prop 注入到 TodoList 組件中。 該組件不再直接導(dǎo)入 TodoService,而是使用注入的服務(wù)來(lái)獲取 todo。

當(dāng)組件安裝時(shí), fetchTodos 函數(shù)使用注入的 todoService 來(lái)檢索 todos。 這樣,我們可以通過(guò)將不同的服務(wù)實(shí)現(xiàn)傳遞給 TodoList 組件來(lái)輕松交換 TodoService 的實(shí)現(xiàn)。

要將 TodoList 組件與 TodoService 的特定實(shí)現(xiàn)一起使用,我們將該服務(wù)作為 prop 傳遞,如下所示:

import React from 'react';
import TodoService from './TodoService';
import TodoList from './TodoList';

function App() {
  return <TodoList todoService={TodoService} />;
}

export default App;

通過(guò)將 TodoService 作為 prop 傳遞給 TodoList 組件,我們實(shí)現(xiàn)了更加模塊化和靈活的設(shè)計(jì),因?yàn)槲覀兛梢暂p松地在 TodoService 的不同實(shí)現(xiàn)之間切換,而無(wú)需更改 TodoList 組件。

在為組件編寫(xiě)測(cè)試時(shí),這非常有用。

此時(shí),我們有兩個(gè)問(wèn)題:

我們?nèi)匀恍枰獙?TodoService 導(dǎo)入到 App 組件中,該組件不使用依賴注入。

props 只是在應(yīng)用程序中傳輸數(shù)據(jù)的有效方法之一,因?yàn)樗鼈儍H適用于嵌套層。

該圖顯示了 props 如何通過(guò)組件的層次結(jié)構(gòu)傳遞。 組件縮進(jìn)得越多,它在組件樹(shù)中的嵌套就越深。 我們不想要這種嵌套。

使用 React Context 進(jìn)行依賴注入

下面是使用 TodoContext 從組件調(diào)用 TodoService 的 React 代碼示例:

import React, { useState, useEffect, useContext } from 'react';
import TodoContext from './TodoContext';function TodoList() {
  const [todos, setTodos] = useState([]);
  const todoService = useContext(TodoContext); // Retrieve TodoService from TodoContext
  useEffect(() => {
    async function fetchTodos() {
      try {
        const todos = await todoService.getTodos(); // Call TodoService from TodoContext to get todos
        setTodos(todos);
      } catch (error) {
        console.error(error);
      }
    }
    fetchTodos();
  }, [todoService]);  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>{todo.title}</li>
      ))}
    </ul>
  );
}
export default TodoList;

在此代碼中,我們使用 useContext 掛鉤從 TodoContext 檢索 TodoService。 然后我們使用檢索到的 todoService 來(lái)獲取 todos。

useEffect 鉤子用于在組件安裝時(shí)獲取待辦事項(xiàng)。 fetchTodos 函數(shù)使用檢索到的 todoService 來(lái)檢索 todos 并將它們?cè)O(shè)置為 todos 狀態(tài)變量。

要使用此組件,我們首先創(chuàng)建一個(gè) TodoContext 并將組件包裝在其中,如下所示:

import React from 'react';
import TodoContext from './TodoContext';
import TodoService from './TodoService';
import TodoList from './TodoList';

function App() {
  return (
    <TodoContext.Provider value={TodoService}>
      <TodoList />
    </TodoContext.Provider>
  );
}

export default App;

在此示例中,我們創(chuàng)建一個(gè) TodoContext 并將 TodoService 作為其值傳遞。 然后,我們將 TodoList 組件包裝在 TodoContext.Provider 組件內(nèi),以便 TodoList 組件可以使用 useContext 掛鉤從上下文中檢索 TodoService。

使用控制反轉(zhuǎn)容器 (IOC) 進(jìn)行依賴注入

使用這個(gè)上下文概念,我們可以再采取一步,使用控制反轉(zhuǎn)容器。

等等,什么是控制反轉(zhuǎn)容器 (IoC)?

在 React 中,IoC(控制反轉(zhuǎn))容器是一種工具,可讓您管理應(yīng)用程序中不同組件和服務(wù)之間的依賴關(guān)系。 它提供了一種方法來(lái)定義和注冊(cè)服務(wù)或?qū)ο螅ㄒ蕾図?xiàng))一次,然后將它們注入到依賴它們的其他組件中。 這有助于解耦組件,并使您的應(yīng)用程序更加模塊化且更易于維護(hù)。

React 中的 IoC 容器通常通過(guò)提供一個(gè)中央注冊(cè)表來(lái)工作,該注冊(cè)表引用可用作依賴項(xiàng)的所有對(duì)象。 組件可以從容器請(qǐng)求這些依賴項(xiàng),而不是直接創(chuàng)建它們。 這種方法還可以輕松地用替代實(shí)現(xiàn)替換依賴項(xiàng)或模擬它們進(jìn)行測(cè)試。

React 有幾種流行的 IoC 容器,例如 InversifyJS、Awilix 和 BottleJS,它們提供了構(gòu)造函數(shù)注入、屬性注入和自動(dòng)依賴解析等各種功能。 一些 IoC 容器比其他容器更復(fù)雜,因此選擇適合您的項(xiàng)目需求和復(fù)雜程度的容器非常重要。

在我們的例子中,我們將從頭開(kāi)始編寫(xiě)一個(gè)示例,如下所示:

import React, { createContext, useContext } from 'react';

// Create a new context for the container
const ContainerContext = createContext();

// Define a component that provides the container to its children
const ContainerProvider = ({ container, children }) => {
  return <ContainerContext.Provider value={container}>{children}</ContainerContext.Provider>;
};

// Define a hook to access the container from within a component
const useContainer = () => {
  const container = useContext(ContainerContext);
  if (!container) {
    throw new Error('Container not found. Make sure to wrap your components with a ContainerProvider.');
  }
  return container;
};

// Define a hook to inject dependencies from the container
const useInject = (identifier) => {
  const container = useContainer();
  return container.resolve(identifier);
};

// Example usage:
const MyService = () => {
  return { foo: 'bar' };
};

const MyComponent = () => {
  const myService = useInject('myService');
  return <div>{myService.foo}</div>; // Output: 'bar'
};

const container = {
  registry: {
    myService: MyService()
  },
  resolve(identifier) {
    if (!this.registry.hasOwnProperty(identifier)) {
      throw new Error(`Object with identifier ${identifier} not found in container`);
    }
    return this.registry[identifier];
  }
};

const App = () => {
  return (
    <ContainerProvider container={container}>
      <MyComponent />
    </ContainerProvider>
  );
};

在此示例中,我們創(chuàng)建一個(gè) ContainerProvider 組件,該組件將容器對(duì)象作為 prop,并使用 ContainerContext 上下文將其提供給其子組件。 我們還定義了一個(gè) useContainer 鉤子,可用于從組件內(nèi)檢索容器。

然后,我們定義一個(gè) MyService 對(duì)象并將其添加到容器對(duì)象的注冊(cè)表屬性中。 我們還在容器對(duì)象上定義了一個(gè)解析方法,該方法采用標(biāo)識(shí)符并從注冊(cè)表中檢索相應(yīng)的對(duì)象。 在本例中,resolve 方法返回 MyService 對(duì)象。

我們用 ContainerProvider 包裝 MyComponent,并將容器對(duì)象作為 prop 傳入,然后渲染 App 組件,該組件渲染用 ContainerProvider 包裝的 MyComponent。 當(dāng)呈現(xiàn) MyComponent 時(shí),它會(huì)從容器中檢索 myService 依賴項(xiàng),并將其 foo 屬性呈現(xiàn)到屏幕上。

在此代碼中,我們添加了一個(gè) useInject 掛鉤,該掛鉤將標(biāo)識(shí)符作為參數(shù)并從容器中檢索相應(yīng)的對(duì)象。 useInject 鉤子在內(nèi)部調(diào)用 useContainer 來(lái)檢索容器,然后調(diào)用容器上的resolve 方法來(lái)檢索對(duì)象。

接下來(lái),我們創(chuàng)建一個(gè) MyComponent,它使用 useInject 掛鉤從容器中檢索 myService 依賴項(xiàng),并將其 foo 屬性呈現(xiàn)到屏幕上。

最后,我們渲染 App 組件,它渲染用 ContainerProvider 包裝的 MyComponent。 當(dāng)呈現(xiàn) MyComponent 時(shí),它使用 useInject 掛鉤從容器中檢索 myService 依賴項(xiàng),并將其 foo 屬性呈現(xiàn)到屏幕上。

總之,依賴注入是一種設(shè)計(jì)模式,它允許更靈活、模塊化且易于測(cè)試的代碼。 它將對(duì)象的創(chuàng)建與其使用分開(kāi),使組件之間的依賴關(guān)系變得明確并促進(jìn)復(fù)雜依賴關(guān)系的管理。

在 React 中,依賴注入可以通過(guò)將服務(wù)作為 props 注入或使用容器通過(guò)鉤子為組件提供依賴關(guān)系來(lái)實(shí)現(xiàn)。 這種做法可以使代碼更清晰、更易于維護(hù),從而更容易重用業(yè)務(wù)邏輯和管理依賴項(xiàng)。

遵循此模式可以提高 React 代碼的可讀性、可維護(hù)性和可測(cè)試性。

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2020-02-18 16:20:03

Redis ANSI C語(yǔ)言日志型

2023-02-10 09:04:27

2022-06-20 09:01:23

Git插件項(xiàng)目

2022-08-01 11:33:09

用戶分析標(biāo)簽策略

2021-04-08 07:37:39

隊(duì)列數(shù)據(jù)結(jié)構(gòu)算法

2023-09-11 08:13:03

分布式跟蹤工具

2020-07-03 08:21:57

Java集合框架

2019-05-14 09:31:16

架構(gòu)整潔軟件編程范式

2023-10-17 08:15:28

API前后端分離

2018-05-22 08:24:50

PythonPyMongoMongoDB

2024-09-23 08:00:00

消息隊(duì)列MQ分布式系統(tǒng)

2017-03-11 22:19:09

深度學(xué)習(xí)

2022-04-07 10:39:21

反射Java安全

2023-11-18 09:30:42

模型AI

2022-05-19 08:28:19

索引數(shù)據(jù)庫(kù)

2019-04-01 10:43:59

Linux問(wèn)題故障

2020-10-18 07:32:06

SD-WAN網(wǎng)絡(luò)傳統(tǒng)廣域網(wǎng)

2022-07-06 12:07:06

Python函數(shù)式編程

2020-10-21 14:12:02

Single Sign

2023-11-06 07:21:13

內(nèi)存結(jié)構(gòu)Jvm
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 一区二区三区高清 | 黄色一级毛片 | 农村真人裸体丰满少妇毛片 | 成人免费一区二区三区视频网站 | 丁香久久| 久操福利| 免费精品一区 | 国产视频精品区 | 国产精品成人av | 亚洲国产一区视频 | 国产精品69av | 在线一区二区国产 | 国产欧美视频一区 | 99精品99| 91福利网| 亚洲成人精品一区二区 | 国产成人福利视频在线观看 | 亚洲成av | 欧美一级片在线播放 | 久久小视频 | www.日日干 | 91av在线免费观看 | 精品视频一区二区三区在线观看 | 天天天天操 | 久久久久国产一级毛片 | 天天综合网91| 伊人网国产| 日本三级日产三级国产三级 | 国产丝袜一区二区三区免费视频 | 欧美日韩国产精品一区 | www四虎影视 | 黄色一级毛片免费看 | 精品久久久久久久久久久久 | 黄色在线播放视频 | 国产伦一区二区三区四区 | 欧美福利视频一区 | 成人在线免费 | www.天天干.com | 日本三级黄视频 | 精品99久久 | 日韩欧美中文字幕在线视频 |