APP 包含 UI 和 state
Redux -- To make state more predictable
在 react 里面, app 里面有很多 component, 并且包含很多 state, 這樣不便于管理.
redux 就是建立一個 state tree, 統(tǒng)一管理
state tree 的作用
- shared cache 不需要一個個傳遞
- predictable state changes 統(tǒng)一設(shè)定改變 state 規(guī)則, how and when 改變 state, 并且可以預(yù)測 (固定死了 type 和 新的 state)
- improved developer tooling 保存 state, 把相關(guān)數(shù)據(jù)聯(lián)系起來
- pure functions 便于測試, 可以預(yù)測
- 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 監(jiān)聽改變的回調(diào)
- the way to update the state tree 更新 state
redux 實(shí)質(zhì)就是發(fā)布訂閱模式的應(yīng)用
- getState 拿到 state tree 里面的所有的 state
- subcribe 就是保存監(jiān)聽函數(shù), 并且返回一個函數(shù), 把這個監(jiān)聽的事件 remove 掉
- action 就是描述 state 的一些信息, 就是用一個 object 來保存提供新的 state 的信息, 提供 type 和 type 對應(yīng)的信息, type 是必須的, state 改變的時候根據(jù) action 里面的 type 和提供的數(shù)據(jù) (比如 id 信息, todo 的內(nèi)容) 來得到一個新的 state (reducer)
{
type: 'add',
todo: {
id: 0,
task: iifj,
complete: false,
}
}
pure function --- 不改變原來的數(shù)據(jù) (類似 slice ) 固定死規(guī)則就 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 聯(lián)系起來
用一個 pure function, 如果 action 的 type 為設(shè)置的 type, 那么就拿到這個 action 的信息, 并且用 concat Store 里面的拿到的初始 state 值 (如果 state 是 undefined, 就設(shè)置為 []) 來返回新的 state, 這樣就不會改變原來的 state 的值, 保證這個函數(shù)是靜態(tài)的, 完全可以預(yù)知的
const todos = (state = [], action) => {
if (action.type === 'add') {
return state.concat([action.todo])
}
return state
}
- reducer 實(shí)質(zhì)
reducer 其實(shí)就是一個監(jiān)聽事件的回調(diào)函數(shù), 當(dāng)觸發(fā) aciton 里面的 type 的時候, 就返回的 state (aciton 里面的 todo 更新到 state 里面去 )
dispatch --- update state
- 參數(shù)為 action, 這樣可以調(diào)用 todos (reducer) 返回新的 state
- 執(zhí)行監(jiān)聽函數(shù), 更加新的 state 來改變一些狀態(tài)或者更新頁面
總結(jié)
- Store 里面保存了所有的 todos
- action 里面保存了 key (type) 和 新的 todo 的信息
- reducer 是監(jiān)聽 type 和 更新 todos 的函數(shù)
- subscribe 保存了一堆回調(diào)函數(shù)
- dispatch 來觸發(fā)
dispatch 就是提供一個 action 的對象 作為參數(shù), reducer 就會找到 action 里面的 type, 如果符合要求, 就調(diào)用改變 todos 的回調(diào)函數(shù), 再根據(jù)新的 todos 執(zhí)行 subscribe 函數(shù)
var createStore = (reducer) => {
// state 是所有的數(shù)據(jù)
let state
// listener 所有的事件函數(shù)
let listeners = []
let o = {}
// getState 是拿到所有的 state
o.getState = () => {
return state
}
// subscribe 保存注冊監(jiān)聽事件, 并且返回一個函數(shù), 用來取消注冊
o.subscribe = (listener) => {
listeners.push(listener)
return () => {
listeners = listeners.filter((l) => l !== listener)
}
}
// dispath a perticular action
// 通過參數(shù) action 來更新 state, 并且調(diào)用所有的監(jiān)聽函數(shù)
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 就是 觸發(fā) reducer 的 type, 和 新的 todo 信息
var action = {
type: 'add',
todo: {
id: 0,
task: 'iifj',
done: false,
}
}
// 參數(shù)是改變 state 的函數(shù) (reducer)
const store = createStore(todos)
// subscribe 就是 store 改變的回調(diào)函數(shù)
var unsubscribe = store.subscribe(() => {
console.log('store', store.getState())
})
// 調(diào)用 reducer 函數(shù)來更新 state, 然后調(diào)用 subscribe 監(jiān)聽函數(shù)
store.dispatch(action)
// 把這個注冊的函數(shù)刪除掉
unsubscribe()
// 這個時候只會增加 state, 但是不會調(diào)用 console.log , 因?yàn)槟莻€函數(shù)被刪除了
store.dispatch(action)
store.getState()