1、何时需要redux
曾经有人说过这样一句话
如果你不知道什么时候应该使用redux,那就是你不需要它
redux的创造者 Dan Abramov 补充过这样一句话
只有当遇到 react 解决不了的问题,才需要 redux
简单说,如果你的UI层非常简单,没有很多互动,Redux 就不需要,用了反而增添复杂性
以下这样情况,都不需要使用 redux
- 用户的使用方式简单
- 用户之间没有协作关系
- 不需要大量服务器交互,也没有使用webSocket
- 视图层(view)只单一来源获取数据
以下情况,才需要使用 redux, redux 适用于多交互,多数据源等操作
- 用户使用方式复杂
- 不同身份的用户有不同的使用方式 (例如:普通用户和管理员)
- 多个用户之间协作关系
- 与服务器之间大量交互,或使用webSocket
- View 要从多个来源获取数据
如果是用于react组件,在以下场景适用于 redux
- 某个组件的状态,需要共享
- 某个状态需要在任何地方都可以拿到
- 一个组件需要改变全局状态
- 一个组件需要改变另一个组件的状态
2、redux 设计思想
Redux 的设计思想很简洁
- Web 应用是一个状态机,视图和状态应该是一 一对应的
- 所有的状态,保存一个对象里面
3、基本概念和 API
- Store
Store 就是保存数据的地方,你可以把它看成一个容器,整个应用只有一个Store。
Redux 提供 createStore 这个函数用来生成 Storeimport {createStore} from "redux"; const store = createStore(fn);
-
State
Store 对象包含所有的数据,如果想得到某个时刻的数据,就要对 Store生成快照,这种集合,叫做State。
当前 Store ,可以通过 getState() 拿到。import {createStore} from "redux"; const store = createStore(fn); //使用 getState() 方法得到 当前的state const state = store.getState();
Redux 规定 一个 State 对应一个 View,只要 State 相同,View 就相同,知道 State 就会知道 View
-
Action
State 的变化,会导致 View 的变化。但是用户接触不到 State,只能接触到 View,所以,State 的变化必须是 View 导致的。因此, Action 就是 View 发出 改变 State 的通知。
Action 是一个对象,期中 type 的属性是必须的,表示 Action 的名称,其他的属性可以自由设置const action = { type: "TO_ADD", text: "Hello" }
上面的代码中,action 的名称是 TO_ADD ,它携带的信息是 "Hello"。
可以理解为,Action 是描述当前发生的事情,也是改变 State 的唯一方法,Action 会运送数据到 Store 中
- store.dispatch
store.dispatch 是 View 发出 Action 的唯一方法。
import {crateStore} from "redux"; const store = createStore(fn); store.dispatch({ type: "TO_ADD", text: "Hello" })
store.dispatch() 方法接受一个 Action 对象作为参数,将它发送出去
-
Reducer
Store 收到 Action 以后,必须要给出一个新的 State,这样 View 才会发生变化,这种 State 的计算过程叫做 Reducer
Reducer 是一个纯函数,它接受 Action 和 当前 State 作为参数,返回一个新的 State
整个应用的初始状态,可以作为 State 的默认值,下面是一个实际的例子
const defaultState = 0; const reducer = (state = defaultState,action)=>{ switch(type){ case "TO_ADD": return state + action.payload dafault: return state } } const state = reduceer(1,{ type:"TO_ADD", parylod:2 })
上面代码中,Reducer 函数收到名为 TO_ADD 的 Action 以后,就返回一个新的 State,作为加法的计算结果,其他的运算逻辑也可以根据 Action 的type不同来实现。
实际应用中,Reducer 函数不用像上面这样手动调用,store.dispatch 方法会触发 Reducer 自动执行,为此,Store 需要制定 Reducer 函数,其做法就是生成 Store 的时候,将 Reducer 传入到 createStore 方法
import {createStore} from "redux"; const store = createStore(reducer);
上面代码中,createStore 将接受一个 reducer 函数作为参数,生成一个新的 store,以后每当 store.dipatch 发动过来一个新的 Action 的时候,就会自动调用 Reducer,从而得到新的 State。
纯函数 - > 只要是同样的输入,就能得到同样的输入
在 Reducer 中规定以下操作不能出现在Reducer中
● 不得改写参数
● 不能调用系统 I/O 的API
● 不能调用Data.now() 或者 Math.random() 等不纯方法,因此每次得到的不一样的结果
由于 Reducer 是纯函数,这样就可以保证同样的 State,必定能得到同样的 View,因此,Reducer 函数里面不能改变 State,必须是返回一个全新的对象。可以参考以下写法
//State 是一个对象 function reducer(state,action){ return Object.assgin({},state,{thingToChange}); //或者 return {...state,...newState} } //State 是一个数组 function reducer(state,action){ return [...state,newItem] }
4、Store的实现
Store提供的三个方法
- store.getState()
- store.dispatch()
- store.subscribe()
store的生成
const createStore = (reducer)=>{
let state;
let listeners = [];
const getState = ()=>{
return state;
}
const dispatch = (action)=>{
state = reducer(state,action);
//当改变state之后,重新执行订阅方法
listeners.forEach((listener)=>{
return listener();
})
}
const subscribe = (listener)=>{
listeners.push(listener);
//该订阅方法返回一个可去取消订阅的方法
return ()=>{
listeners = listeners.filter((listener)=>{
return listener != listener
})
}
}
dispatch({})
return {getState, dispatch, subscribe}
}
5、工作流程
下面Redux的流程图
首先,用户发出 Action
store.dispatch();
然后,store自动调用reducer,并且传入2个参数,当前state和action,Reducer会返回新的state
let nextState = toadd(previousState,action);
state 一旦有变化,store就会调用监听函数
//设置监听函数
store.subsctibe(listener);
listener 可以通过store.getState() 得到当前的状态,如果使用的是 React,这时可以出发重新渲染 View
function listerner(){
let newState = store.getState();
component.setState(newState);
}
详情请移步阮一峰老师的网站教程:http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html