零. 介绍
随着 JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 state (状态) . Redux 试图让 state 的变化变得可预测。这些限制条件反映在 Redux 的三大原则中。
三大原则
- 单一数据源:
- 整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中。
- State 是只读的
- 唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
- 使用纯函数来执行修改
- 为了描述 action 如何改变 state tree ,你需要编写 reducers。
一. 几个概念
以上提及了几个概念: Action
, Reducer
,Store
Action
Action
是把数据从应用传入到store
的有效荷载. 也是store
数据的唯一来源. 一般来说你会通过 store.dispatch()
将 action 传到 store。
Reducer
Reducers 指定了应用状态的变化如何响应 actions 并发送到 store 的,记住 actions 只是描述了有事情发生了这一事实,并没有描述应用如何更新 state。
Store
store是把Action和Reducer联系在一起的对象. 它提供很多方法,方便操作
- 维持应用的 state;
- 提供
getState()
方法获取 state; - 提供
dispatch(action)
方法更新 state; - 通过
subscribe(listener)
注册监听器; - 通过
subscribe(listener)
返回的函数注销监听器。
二.使用流程
store 使用 createStore()
进行创建.
- 写法如下, 就把 reducers 和store 联系起来了.
import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)
- store 发起一个 action
// 定义action
const ADD_TODO = 'ADD_TODO'
function addTodo(text) {
return {
type: ADD_TODO,
text
}
}
// 发起一个 action
store.dispatch(addTodo('Learn about actions'))
- 定义reducer处理 ADD_TODO
import {
ADD_TODO,
} from './actions'
function todoApp(state = initialState, action) {
switch (action.type) {
case ADD_TODO:
return Object.assign({}, state, {
todos: [
...state.todos,
{
text: action.text,
completed: false
}
]
})
default:
return state
}
}
-
subscribe(listener)
添加监听者
store.dispatch(addTodo('Learn about actions'))
上面的方法执行完成后.这个新的树就是应用的下一个 state!所有订阅 store.subscribe(listener)
的监听器都将被调用;监听器里可以调用 store.getState()
获得当前 state。
三.几个方法
createStore()
通过上面的简单流程可以看出, createStore()
返回的 store 的重要性. store提供的几个方法也是及其重要,
- 简单实现
connect()
React 数据传递是单向通过 props 传递, 容器组件就是使用 store.subscribe()
从 Redux state 树中读取部分数据,并通过 props 来把这些数据提供给要渲染的组件。你可以手工来开发容器组件,但建议使用 React Redux 库的 connect()
方法来生成,这个方法做了性能优化来避免很多不必要的重复渲染。(这样你就不必为了性能而手动实现 React 性能优化建议 中的 shouldComponentUpdate
方法。)
- 简单实现
四.特殊组件
Provider
在和 搭配 React 使用的时候, connect()是必不可少的方法. 所有容器组件都可以访问 Redux store,所以可以手动监听它。一种方式是把它以 props 的形式传入到所有容器组件中。但这太麻烦了,因为必须要用 store
把展示组件包裹一层,仅仅是因为恰好在组件树中渲染了一个容器组件。
建议的方式是使用指定的 React Redux 组件 <Provider>
来 魔法般的 让所有容器组件都可以访问 store,而不必显式地传递它。只需要在渲染根组件时使用即可。
- 简单实现