APP 包含 UI 和 state
Redux -- To make state more predictable
在 react 里面, app 里面有很多 component, 并且包含很多 state, 这样不便于管理.
redux 就是建立一个 state tree, 统一管理
state tree 的作用
- shared cache 不需要一个个传递
- predictable state changes 统一设定改变 state 规则, how and when 改变 state, 并且可以预测 (固定死了 type 和 新的 state)
- improved developer tooling 保存 state, 把相关数据联系起来
- pure functions 便于测试, 可以预测
- server rendering 不需要 split data, 一个大容器来管理就好了
Store 是什么, 做了什么事情 --- 保存 state, 并且处理 state
- state tree 保存 state
- the way to get the state from the state tree 获取所有的 state
- the way to listen the state tree change 监听改变的回调
- the way to update the state tree 更新 state
redux 实质就是发布订阅模式的应用
- getState 拿到 state tree 里面的所有的 state
- subcribe 就是保存监听函数, 并且返回一个函数, 把这个监听的事件 remove 掉
- action 就是描述 state 的一些信息, 就是用一个 object 来保存提供新的 state 的信息, 提供 type 和 type 对应的信息, type 是必须的, state 改变的时候根据 action 里面的 type 和提供的数据 (比如 id 信息, todo 的内容) 来得到一个新的 state (reducer)
{
type: 'add',
todo: {
id: 0,
task: iifj,
complete: false,
}
}
pure function --- 不改变原来的数据 (类似 slice ) 固定死规则就 predictable
- always return the same result given the same arguments.
- execution doesn't depend on the state of the application.
- don't modify the variables outside of their scope.
Reducer 是 pure function
- 如何把 state 和 action 联系起来
用一个 pure function, 如果 action 的 type 为设置的 type, 那么就拿到这个 action 的信息, 并且用 concat Store 里面的拿到的初始 state 值 (如果 state 是 undefined, 就设置为 []) 来返回新的 state, 这样就不会改变原来的 state 的值, 保证这个函数是静态的, 完全可以预知的
const todos = (state = [], action) => {
if (action.type === 'add') {
return state.concat([action.todo])
}
return state
}
- reducer 实质
reducer 其实就是一个监听事件的回调函数, 当触发 aciton 里面的 type 的时候, 就返回的 state (aciton 里面的 todo 更新到 state 里面去 )
dispatch --- update state
- 参数为 action, 这样可以调用 todos (reducer) 返回新的 state
- 执行监听函数, 更加新的 state 来改变一些状态或者更新页面
总结
- Store 里面保存了所有的 todos
- action 里面保存了 key (type) 和 新的 todo 的信息
- reducer 是监听 type 和 更新 todos 的函数
- subscribe 保存了一堆回调函数
- dispatch 来触发
dispatch 就是提供一个 action 的对象 作为参数, reducer 就会找到 action 里面的 type, 如果符合要求, 就调用改变 todos 的回调函数, 再根据新的 todos 执行 subscribe 函数
var createStore = (reducer) => {
// state 是所有的数据
let state
// listener 所有的事件函数
let listeners = []
let o = {}
// getState 是拿到所有的 state
o.getState = () => {
return state
}
// subscribe 保存注册监听事件, 并且返回一个函数, 用来取消注册
o.subscribe = (listener) => {
listeners.push(listener)
return () => {
listeners = listeners.filter((l) => l !== listener)
}
}
// dispath a perticular action
// 通过参数 action 来更新 state, 并且调用所有的监听函数
o.dispatch = (action) => {
state = reducer(state, action)
listeners.forEach((listener) => listener() )
}
return o
}
// todos 就是 reducer, 找到 action 的 type 和 store 里面的所有的 state
// 返回新的 state
const todos = (state = [], action) => {
if (action.type === 'add') {
return state.concat([action.todo])
}
return state
}
// action 就是 触发 reducer 的 type, 和 新的 todo 信息
var action = {
type: 'add',
todo: {
id: 0,
task: 'iifj',
done: false,
}
}
// 参数是改变 state 的函数 (reducer)
const store = createStore(todos)
// subscribe 就是 store 改变的回调函数
var unsubscribe = store.subscribe(() => {
console.log('store', store.getState())
})
// 调用 reducer 函数来更新 state, 然后调用 subscribe 监听函数
store.dispatch(action)
// 把这个注册的函数删除掉
unsubscribe()
// 这个时候只会增加 state, 但是不会调用 console.log , 因为那个函数被删除了
store.dispatch(action)
store.getState()
网友评论