前言
随着网页开发越来越复杂,JavaScript 的单线程、事件循环和全局变量等缺点逐渐被暴露出来。为了解决这些问题,Facebook 推出了 Flux 架构和 Redux 库。其中 Flux 是 Facebook 官方架构,而 Redux 则是基于 Flux 架构实现的一个独立库。
Redux 作为一种状态管理工具,既可以使用于 React,也可以使用于其他框架或纯 JavaScript 应用。本文将详细阐述 Redux 的数据流,并通过示例代码给出实际应用指导。
数据流
Redux 是一种单向数据流的状态管理工具,其状态数据流向遵从以下模式:
Action:动作对象,用于描述状态的变化。Action 对象包含
type
字段和其他自定义字段。const action = { type: 'ADD_TODO', text: 'Learn Redux', };
Store:状态树。一个应用程序只能有一个状态树,它存储了整个应用程序的状态。
-- -------------------- ---- ------- ----- ------------ - - ------ --- ----------------- ----------- -- -------- ------------- - ------------- ------- - -- --- ------ ------ - ----- ----- - ---------------------
Reducer:处理状态变化的纯函数。它接收当前 State 和一个 Action 对象,根据 Action 的类型返回一个新的 State。Reducer 函数需要保证无副作用,也就是说,在同样的输入参数下,每次调用都返回相同的输出。
-- -------------------- ---- ------- -------- ----------- - --- ------- - ------ ------------- - ---- ----------- ------ - --------- - ----- ------------ ---------- ------ -- -- ---- -------------- ------ ---------------- ------ -- - -- ------ --- ------------- - ------ - -------- ---------- ---------------- -- - ------ ----- --- -------- ------ ------ - - -------- ---------------------- - ----------- ------- - ------ ------------- - ---- ------------------------ ------ -------------- -------- ------ ------ - - -------- ------------- - --- ------- - ------ - ------ ------------------ -------- ----------------- ---------------------------------------- -------- -- -
Dispatch:分发 Action,通知 Reducer 产生新的 State。
store.dispatch({ type: 'ADD_TODO', text: 'Learn Redux', });
Subscribe:监听 State 的变化。
function listener() { console.log(store.getState()); } store.subscribe(listener);
示例代码
下面通过一个 Todos 应用的示例代码来详细说明 Redux 的数据流:
-- -------------------- ---- ------- ------ - ----------- - ---- -------- -- ------ -- ----- -------- - ----------- ----- ----------- - -------------- ----- --------------------- - ------------------------ -- ----- ----- ----------------- - - --------- ----------- --------------- ----------------- ------------ -------------- -- -- ------ ---- -------- ------------- - ------ - ----- --------- ----- -- - -------- ----------------- - ------ - ----- ------------ ------ -- - -------- --------------------------- - ------ - ----- ---------------------- ------- -- - -- ------- -------- ----------- - --- ------- - ------ ------------- - ---- --------- ------ - --------- - ----- ------------ ---------- ------ -- -- ---- ------------ ------ ---------------- ------ -- - -- ------ --- ------------- - ------ - -------- ---------- ---------------- -- - ------ ----- --- -------- ------ ------ - - -------- ---------------------- - --------------------------- ------- - ------ ------------- - ---- ---------------------- ------ -------------- -------- ------ ------ - - -------- ------------- - --- ------- - ------ - ------ ------------------ -------- ----------------- ---------------------------------------- -------- -- - -- -- ----- ----- ----- - --------------------- -- -- -------- ------------------ -- - ------------------------------ --- -- -- ------ ----------------------------- --------- -- ------- ------ ------- ---------- ------- ----------------------------- -------------- -- ------- ------ ------- ---------- ------- ------ ------ ------------ ---------- ------- ------------------------------ -- ------- ------ ------- ---------- ------ ------ ------ ------------ ---------- ------- ---------------------------------------------------------------------- -- ------- ------- ------ ------- ---------- ------ ------ ------ ------------ ---------- -------- ----------------- -----------------
在上述示例代码中,首先定义了三个 Action 类型,分别代表添加待办、切换完成状态和设置过滤器三种操作。然后定义了三个 Action 创建函数来分别创建这些 Action 对象。接着通过定义两个 Reducer,一个用于操作 Todos 的状态,另一个用于操作过滤器的状态,并将二者合并成一个 Root Reducer。最后通过 createStore
函数创建 Store 实例,并在该 Store 实例上注册 Listener,派发 Action。每次 Action 执行后,都将通过 Listener 输出更新后的状态信息。
结论
本文详细阐述了 Redux 的单向数据流模式,并通过示例代码演示了其基本用法。Redux 的数据流模式的主要作用是解耦组件之间的状态关系,并使数据的流向可控,从而提升代码的可维护性和可测试性。对于组件生命周期等钩子函数的调用时机也没有要求,因此在大型应用中更加灵活。对于不同的应用场景,可以选择合适的状态管理工具,并结合具体情况进行使用。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/670761c1d91dce0dc8678587