设计思想
- Web应用是一个状态机,视图与状态一一对应
- 所有状态都保存在一个对象中
安装
npm install --save redux
附加包
npm install --save react-redux
npm install --save-dev redux-devtools
Redux的核心
1 { type: 'ADD_TODO', text: 'Go to swimming pool' }
2 { type: 'TOGGLE_TODO', index: 1 }
3 { type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }
下面详细阐述一下各个核心:
Ⅰ. Store
生成Store容器:createStore函数接收另外一个函数作为参数,返回一个Store对象。
import { createStore } from 'redux';
const store = createStore(fn);
Ⅰ. Ⅰ Store 的实现
Store 提供了三个方法。
store.getState()
store.dispatch()
store.subscribe()
import { createStore } from 'redux';let { subscribe, dispatch, getState } = createStore(reducer);
createStore方法还可以接受第二个参数,表示 State 的最初状态。这通常是服务器给出的。
let store = createStore(todoApp, window.STATE_FROM_SERVER)
上面代码中,window.STATE_FROM_SERVER就是整个应用的状态初始值。注意,如果提供了这个参数,它会覆盖 Reducer 函数的默认初始值。
下面是createStore方法的一个简单实现,可以了解一下 Store 是怎么生成的。
const createStore = (reducer) => { let state; let listeners = []; const getState = () => state; const dispatch = (action) => { state = reducer(state, action); listeners.forEach(listener => listener()); }; const subscribe = (listener) => { listeners.push(listener); return () => { listeners = listeners.filter(l => l !== listener); } }; dispatch({}); return { getState, dispatch, subscribe };};
Ⅱ. State —— 获取:store.getState()
Store对象包含了所有的数据。而State是Store的数据集合,通过 store.getState() 可以拿到State.
import { createStore } from 'redux';
const store = createStore(fn);// 在生成 Store 的时候,将 Reducer 传入createStore方法
const state = store.getState();
Redux 规定, 一个 State 对应一个 View。只要 State 相同,View 就相同。你知道 State,就知道 View 是什么样,反之亦然。
1 function visibilityFilter(state = 'SHOW_ALL', action) { 2 if (action.type === 'SET_VISIBILITY_FILTER') { 3 return action.filter; 4 } else { 5 return state; 6 } 7 } 8 9 function todos(state = [], action) { 10 switch (action.type) { 11 case 'ADD_TODO': 12 return state.concat([{ text: action.text, completed: false }]); 13 case 'TOGGLE_TODO': 14 return state.map((todo, index) => 15 action.index === index ? 16 { text: todo.text, completed: !todo.completed } : 17 todo 18 ) 19 default: 20 return state; 21 } 22 }
Ⅲ. Action
State的变化回导致View的变化,但是用户解除不到View,只能接触到State。所以,State的变化一定是View导致的。
Action是View发出的通知,表示State将要发生变化了。
Action 是一个对象。其中的type属性是必须的,表示 Action 的名称。其他属性可以自由设置,社区有一个规范可供参考。
const action = {
type: 'ADD_TODO',
payload: 'Learn Redux'};
- Action Creator
View 要发送多少种消息,就会有多少种 Action。如果都手写,会很麻烦。可以定义一个函数来生成 Action,这个函数就叫 Action Creator。
const ADD_TODO = '添加 TODO';
function addTodo(text) {
return {
type: ADD_TODO,
text
}}
const action = addTodo('Learn Redux');
Ⅳ. Reducer
const reducer = function (state, action) {
// ...
return new_state;};
整个应用的初始状态,可以作为 State 的默认值。下面是一个实际的例子。
const defaultState = 0;
const reducer = (state = defaultState, action) => {
switch (action.type) {
case 'ADD':
return state + action.payload;
default:
return state;
}};
const state = reducer(1, {
type: 'ADD',
payload: 2});
import { createStore } from 'redux';
const store = createStore(reducer);
const actions = [
{ type: 'ADD', payload: 0 },
{ type: 'ADD', payload: 1 },
{ type: 'ADD', payload: 2 }];
const total = actions.reduce(reducer, 0); // 3
上面代码中,数组actions表示依次有三个 Action,分别是加0、加1和加2。数组的reduce方法接受 Reducer 函数作为参数,就可以直接得到最终的状态3。
Ⅳ.Ⅰ Reducer是一个纯函数
不得改写参数 不能调用系统 I/O 的API 不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果
// State 是一个对象
function reducer(state, action) {
return Object.assign({}, state, { thingToChange });
// 或者
return { ...state, ...newState };}
// State 是一个数组
function reducer(state, action) {
return [...state, newItem];}
这是一条小尾巴ヾ(o◕∀◕)ノヾ~
须知少日拏云志,曾许人间第一流!
浙公网安备 33010602011771号