NgRx 与 RxJS: 一个应用实战

AI 编程助手,豆包旗下的编程助手,提供智能补全、智能预测、智能问答等能力,节省开发时间,释放脑海中的创造力,支持 VSCode,点击体验 AI

前言

在前端开发中,状态管理是非常重要的一部分。而随着现代化 Web 应用逐渐兴起,单向数据流架构也成为越来越多开发者的选择。NgRx 就是 Angular 中的一种实现单向数据流的解决方案,它的核心依赖——RxJS 也是前端开发者必须掌握的一项技能。

本文将会介绍如何在 Angular 应用中使用 NgRx/RxJS 进行状态管理。为了让读者有一个更加直观的理解,我们将通过一个简单的 TodoList 应用来进行演示。我们将探讨以下主题:

  1. 如何使用 NgRx Store 来管理状态
  2. 如何使用 NgRx Effect 来处理异步请求
  3. 如何使用 RxJS 来过滤和转换数据

安装依赖

在开始之前,请先确保已经安装了 Angular CLI,并创建了一个空的 Angular 项目。我们需要安装一些 NgRx 相关的依赖:

--- ------- ----------- ------------- ------

然后,我们需要引入 RxJS。RxJS 也是一个非常强大的库,它提供了一系列的操作符和 Observable,可以方便地进行各种数据流的处理。我们可以这样安装:

--- ------- ---- ------

当然,为了实现 TodoList 应用的界面,我们还需要 angular-material 和 flex-layout。这里不再多赘述,请读者自行安装。

创建 Store 和 Actions

我们需要先思考一下 TodoList 应用中都有哪些状态需要管理。这里我们只考虑最简单的 TodoList,所以只需要考虑以下两个状态:

  1. TodoList 中所有的任务列表
  2. 当前被选中的任务

我们在应用的根目录中新建一个叫做 store 的文件夹,然后在该文件夹中创建一个 actions.ts 文件:

------ - ------------- ----- - ---- --------------

------ ----- ------- - -------------
  ----------- --- ------
  ------- ----- ------ ----
--

------ ----- ---------- - -------------
  ----------- ------ ------
  ------- --- ------ - ---- ----
--

------ ----- ---------- - -------------
  ----------- ------ ------
  ------- --- ------ ----
--

------ ----- ---------- - -------------
  ----------- ------ ------
  ------- --- ------ ----
--

actions.ts 文件中,我们定义了 4 个 Action:addTask、selectTask、deleteTask 和 toggleTask,分别对应添加任务、选择任务、删除任务和完成任务等操作。其中,每一个 Action 都有一个对应的字符串类型('[TodoList] Add Task'),它们是用来区分这个 Action 的,也就是用来告诉 Store 要对这个 Action 做出什么样的改变。

注意:这里的 '[TodoList]' 前缀是可以自己定义的。本文中,为了方便区分不同的 Action,我们把它们都放在了 [TodoList] 的命名空间下。

接着,我们继续在 store 文件夹下创建一个 reducers.ts 文件:

------ - -------------- -- - ---- --------------
------ - -------- ----------- ----------- ---------- - ---- ------------

------ --------- ---- -
  --- -------
  ----- -------
  ---------- --------
-

------ --------- ----- -
  ------ -------
  ----------- ------ - -----
-

------ ----- ------------- ----- - -
  ------ ---
  ----------- ----
--

------ ----- ----------- - --------------
  -------------
  ----------- ------- - ---- -- -- --
    ---------
    ------ -
      ---------------
      - --- ---------------------------------------- ----- ---------- ----- -
    -
  ----
  -------------- ------- - -- -- -- --
    ---------
    ----------- --
  ----
  -------------- ------- - -- -- -- --
    ---------
    ------ ----------------------- -- ------- --- ---
  ----
  -------------- ------- - -- -- -- --
    ---------
    ------ -------------------- --
      ------- --- -- - - -------- ---------- --------------- - - ----
    -
  ---
--

在这里,我们定义了一个叫做 todoReducer 的 Reducer。它包含两个状态:todosselectedId。在 initialState 中,我们初始化了这两个状态的默认值。然后我们使用 createReducer 方法来创建这个 Reducer,它将接收多个类似于 on(addTask, reducerFunction) 的对象作为参数。在这其中,每一个对象将会对应一个 Action,并且它会接收一个 Reducer 函数作为第二个参数。这个 Reducer 函数将会在 Action 被触发的时候被执行。

在本例中,我们将 Reducer 函数命名为 todoReducer,然后它接收四个 Action,并且执行相应的操作,以改变 Store 中的状态值。具体地讲,我们在 addTask 中添加了一个新的任务,在 selectTask 中选择了当前的任务,在 deleteTask 中删除了指定的任务,而在 toggleTask 中切换了任务的完成状态。

创建 Effects

接着,我们需要处理一下异步操作。对于 TodoList 应用来说,最常见的异步操作可能就是从服务器端加载数据了。我们可以在 store 文件夹下再新建一个 effects.ts 文件:

------ - ---------- - ---- ----------------
------ - -------- ------------- ------ - ---- ----------------
------ - -- - ---- -------
------ - ---------- ----------- --- - ---- -----------------
------ - ----------- - ---- ------------------
------ - ------- - ---- ------------

-------------
------ ----- ----------- -
  --------- - --------------- --
    -------------------
      ------------------ ---- -------
      ------------ --
        ------------------------------------
          --------- -- --------- ----- ----- ----
          ------------- -- ---- ----- ----------- ---- ---- -------- ---
        -
      -
    -
  --

  ------------------- --------- -------- ------- ------------ ------------ --
-

首先,我们要注入一个 TodoService,用来从服务器端加载数据。然后,我们定义了一个叫做 loadTodo$ 的 Effect,在这个 Effect 中,我们使用 switchMap 操作符将 getTodoList() 的结果映射为 addTask 关联的任务对象。如果操作成功,它将返回一个 addTask Action,并且任务将被添加到 TodoList 中。如果操作失败,我们将返回一个 Load Todo Failure 的 Action。

effects.ts 文件中,我们还需要定义一个 EffectsModule 来将 TodoEffects 注册到我们的应用程序中。我们可以在 AppModule 中这样写:

------ - -------- - ---- ----------------
------ - ------------- - ---- ----------------------------
------ - ---------------- - ---- -----------------------
------ - ------------ - ---- ------------------
------ - ----------------------- - ---- ---------------------------------------
------ - ---------------- - ---- -----------------------
------ - ----------- - ---- --------------
------ - ------------- - ---- ----------------
------ - ------- - ---- -------------------
------ - ----------- - ---- ------------------

-----------
  ------------- ---------------
  -------- -
    --------------
    -----------------
    ------------------------
    -----------------
    --------------------- ---------- ------- ---
    ------------------------------------
  --
  ---------- ---
  ---------- --------------
--
------ ----- --------- --

注意:在这里,我们使用了 forRoot 方法来注册 Reducer 和 Effects。如果你的应用程序是一个子模块,你应该使用 forFeature 方法来注册它们。

结合 RxJS 处理数据

现在,我们已经完成了 Store 和 Effects 的创建。但是,我们还需要通过 RxJS 来处理数据,才能使我们的 TodoList 更加有效和可读。我们可以在 todo-list.component.ts 文件中这样写:

------ - ---------- ------ - ---- ----------------
------ - ----- - ---- --------------
------ - ---------- - ---- -------
------ - ------ - ---- -----------------
------ - -------- ----------- ----------- ---------- - ---- -------------------
------ - ------ ---- - ---- --------------------

------------
  --------- ----------------
  ------------ -----------------------------
  ---------- ------------------------------
--
------ ----- ----------------- ---------- ------ -
  ------- ------------------ - --- ---------------------
  ------------ ----------------- - ----- - --- ----------------- - --------
  ----- ------ - ---

  ------------------- ------ ------- ---------- ----- --- --

  ---------- -
    ----------- - ----------------------- -- -----------------------
    ---------------- - ----------------------- -- ----------------------------
  -

  -------------- ----- -
    -------------------------------- --- ------- ----
  -

  ------------ ------- -
    -------------------------------- -- ----
  -

  ------------ ------- -
    -------------------------------- -- ----
  -

  ---------- -
    -- ----------------- --- --- -
      -------
    -
    ----------------------------- ----- --------- ----
    --------- - ---
  -

  --- ---------------- ---------------- -
    ------ -----------------
      ------------ -- ---------
      ------------ -- --------------------
      ------------ -- ----------------- -- ------- --- -------------------
      --------- -- --------------- -- ------- --- ------------------
    --
  -
-

在上面的代码中,我们让应用程序能够选择任务(onSelect)、删除任务(onDelete)和完成任务(onToggle)。同时,我们也允许用户添加新的任务。这些方法都包含在这个组件中,但是我们需要将它们和 Store 中的状态值联系起来。

首先,我们需要订阅 selectedId$todos$ 这两个 Observable。然后,我们可以定义一个 selectedTask$ 的 Observable,它将只会发射被选中的任务。我们可以通过使用 filtermap 操作符来实现这一点。我们还可以通过 pipesubscribe 来创建其他的 Observable,以便我们可以更好地控制数据的流动。

结论

至此,我们已经完成了使用 NgRx 和 RxJS 来构建一个 TodoList 的应用的全部内容。NgRx Store 负责管理我们的应用程序状态,NgRx Effect 允许我们通过异步的方式来调用服务器端的 API,而 RxJS 则将作为数据处理的主要工具,方便我们对数据做各种转换和处理。

本文介绍了在 Angular 应用中如何使用 NgRx 和 RxJS 这两个库来构建 TodoList 应用。我们从定义 Reducer 开始,然后介绍了如何处理异步操作,并通过 RxJS 的操作符和 Observable 配合起来进行数据转换和处理。本文的示例代码可从 Github仓库 下载,供读者参考学习。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/671c34d49babaf620faf9a75


猜你喜欢

  • Hapi.js 的使用方法总结(二)

    在上一篇文章中,我们介绍了 Hapi.js 的一些基础知识和使用方法。在本篇文章中,我们将更深入地探究 Hapi.js 的用法。我们将主要讨论以下三个方面: 路径参数 认证和授权 插件和中间件 路...

    14 天前
  • 使用 Node.js 和 Express 构建 RESTful API:配置和调试

    在Web开发中,API是一种用于不同应用程序之间交换数据的技术。使用API,可以使不同的应用程序之间进行通信并共享数据,从而实现更强大、更灵活的应用程序。 RESTful API是目前比较流行的一种A...

    14 天前
  • Koa 框架中间件开发详解及实践分享

    前言 如今,随着互联网技术的不断发展和进步,前端 web 开发也变得日益重要。而在这个领域中,Koa 框架无疑是一个非常流行的技术。Koa 框架是一个轻量级的 Node.js web 框架,它基于 E...

    14 天前
  • 为什么 Material Design 的颜色更加鲜活、明亮?

    Material Design 是 Google 推出的一种现代化的设计语言,该语言具有鲜活、明亮的颜色风格,深受众多设计师和开发者的喜爱。那么,为什么 Material Design 的颜色更加鲜活...

    14 天前
  • ECMAScript 2018 中 Generator 函数的应用场景与实例演示

    前言 Generator 函数作为 ECMAScript 2018 的新特性,在 ES6 的基础上进一步增强了 JavaScript 的编程能力。本文将会详细介绍 Generator 函数的应用场景以...

    14 天前
  • 使用 Tailwind CSS 解决响应式设计的问题

    在现代 Web 开发中,响应式设计已经成为必备技能。对于前端开发人员而言,实现网站或应用程序在不同屏幕尺寸之间的平滑过渡是一项重要任务。但是,在大多数情况下,响应式设计需要大量的 CSS 编写,这会导...

    14 天前
  • Headless CMS 的优势与劣势分析

    Headless CMS 是一种新型的内容管理系统,近年来在前端开发领域中越来越流行。与传统 CMS 不同的是,Headless CMS 是一种无头 CMS,它通过提供 API 端点,让前端开发者可以...

    14 天前
  • Redis 在分布式系统中的使用及常见问题及处理方法

    前言 随着分布式系统的兴起和应用场景的不断扩大,分布式系统中数据的管理和处理越来越受到关注。Redis 作为一种高性能的键值存储数据库,已经成为分布式系统数据存储和缓存的重要选择之一。

    14 天前
  • Cypress 中如何模拟 fetch 时返回异常的情况

    在前端开发中,我们经常会使用 fetch 方法来与后端API进行数据交互。在测试前端页面时,我们需要模拟 fetch 方法返回异常的情况,以便测试我们的应用程序在处理错误时的表现。

    14 天前
  • 优化 Elasticsearch 性能的几种方法

    Elasticsearch 是一个基于 Lucene 的分布式搜索引擎,它是现代 Web 应用、日志聚合、企业搜索等领域的重要组成部分。对于任何开发人员来说,优化 Elasticsearch 的性能是...

    14 天前
  • 避免 RxJS 中的内存泄漏问题

    RxJS 是一个流式编程的库,它提供了一系列方便的工具和函数,帮助我们处理异步数据流。它在前端开发中被广泛地应用,但是在使用 RxJS 时也有一些需要注意的问题,比如它与内存泄漏的关系。

    14 天前
  • 如何在 Deno 中优化大批量数据处理

    前言 Deno 是一个安全、现代化的 JavaScript 和 TypeScript 运行时环境。它内置了一些常见的工具,可以使我们尽可能简单、快速地实现我们的各种愿望。

    14 天前
  • 如何利用 ECMAScript 2018 中的 Object.defineProperty 实现双向绑定

    如何利用 ECMAScript 2018 中的 Object.defineProperty 实现双向绑定 随着前端技术的发展,双向绑定成为了开发中的一项重要功能需求。

    14 天前
  • ESLint:如何提高所有开发者代码规范性?

    在前端开发的过程中,代码风格的一致性和规范性一直是一个非常重要的问题。如果没有一个统一的风格规范,那么代码会显得混乱无章,可读性也会变得很差。为了解决这个问题,我们通常会使用一些工具来自动化检查和修复...

    14 天前
  • Next.js 中如何使用 GraphQL 及其优化

    简介 在 Web 开发中, GraphQL 作为一种新兴的 API 查询语言,具有多种优势。在前端的开发过程中,我们经常需要通过查询接口获取后端返回的数据,而 GraphQL 可以让你的应用程序更直接...

    14 天前
  • 使用 Server-sent Events(SSE)进行大规模数据推送的最佳实践

    Server-sent Events(SSE)是一种基于 HTTP 的推送技术,它允许服务器实时向客户端推送事件数据,而无需客户端发送请求。相比于 WebSocket 等技术,SSE 更加简洁易用,适...

    14 天前
  • 在 Deno 中使用 Kubernetes 部署的最佳实践

    随着 Deno 的发展,使用 Kubernetes 部署 Deno 应用程序已经成为前端开发的常见方式。Kubernetes 不仅提供了高效的容器编排工具,还可以帮助开发者轻松部署和扩展应用。

    14 天前
  • 如何解决 Koa2 常见的 “ctx is not defined” 错误

    问题描述 当使用 Koa2 编写应用程序时,有时会遇到 "ctx is not defined" 的错误。这通常意味着在代码中使用了 ctx 变量,但是它未被定义或赋值。

    14 天前
  • Tailwind CSS 中的样式优化技巧

    前言 在前端开发中,样式的重要性不言而喻。好的样式既可以为页面增色,也可以为用户提供更好的体验。然而,在实际开发中,样式的编写往往需要耗费大量的时间和精力,特别是对于大型项目来说更是如此。

    14 天前
  • Kubernetes 中的 DaemonSet 和 StatefulSet

    什么是 DaemonSet DaemonSet 是 Kubernetes 中一种控制器对象,可以确保一个 Pod 在某些或所有节点上运行。DaemonSet 能够在所有节点上自动创建 Pod 并保证 ...

    14 天前

相关推荐

    暂无文章