本文主要介紹redux的react-redux的原理
redux原理
github地址:https://github.com/majunchang/miniRedux
原生react的調(diào)用和常用方法
react流程圖展示
- redux中有一個(gè)reducer函數(shù)和action 通過(guò)dispatch(action)來(lái)觸發(fā)reducer的對(duì)應(yīng)的case
- 提供一個(gè)createStore方法 傳入reducer 返回的對(duì)象中包含getState和subscribe和dispatch方法
調(diào)用示例:
redux 原生版的調(diào)用 getState()獲取狀態(tài) subscribe()進(jìn)行監(jiān)聽(tīng) dispatch()觸發(fā)相應(yīng)的action 改變state
import { createStore } from './woniuRedux/woniuRedux'
// 這就是reducer處理函數(shù)坦报,參數(shù)是狀態(tài)和新的action
export function counter (state = 0, action) {
// let state = state||0
console.log(action)
console.log(state)
switch (action.type) {
case '加蘋(píng)果':
return state + 1
case '吃蘋(píng)果':
return state - 1
default:
return 10
}
}
const store = createStore(counter)
// console.log
const init = store.getState()
console.log(`一開(kāi)始有${init}個(gè)蘋(píng)果`)
function listener () {
const current = store.getState()
console.log(`現(xiàn)在有${current}個(gè)蘋(píng)果`)
}
// 訂閱,每次state修改稚失,都會(huì)執(zhí)行l(wèi)istener
store.subscribe(listener)
// 提交狀態(tài)變更的申請(qǐng)
store.dispatch({ type: '加蘋(píng)果' })
store.dispatch({ type: '加蘋(píng)果' })
store.dispatch({ type: '加蘋(píng)果' })
store.dispatch({ type: '吃蘋(píng)果' })
store.dispatch({ type: '吃蘋(píng)果' })
redux實(shí)現(xiàn)原理(源碼解析)(簡(jiǎn)易版)
主要介紹createStore applyMiddleware和bindActionCreators
caeateStore 源碼解讀
export function createStore (reducer, enhancer) {
if (enhancer) {
console.log('enhancer', enhancer) ①
return enhancer(createStore)(reducer)
// return applymiddleware(thunk)(createStore)(reducer)
}
let currentState = {}
let currentListeners = []
function getState () {
return currentState
}
function subscribe (listener) {
currentListeners.push(listener)
}
function dispatch (action) {
currentState = reducer(currentState, action)
currentListeners.forEach(v => {
v()
})
return action
}
// 初次調(diào)用的時(shí)候 首先執(zhí)行一次 dispatch
dispatch({type: '@@redux/firstTime'})
return {getState, subscribe, dispatch}
}
- createStore 內(nèi)部是一個(gè)觀察者模式鸣皂, subscribe 添加注冊(cè)函數(shù) dispatch讓函數(shù)自調(diào)用
- 首次調(diào)用createStore的時(shí)候 內(nèi)部會(huì)執(zhí)行一次dispatch 將reducer綁定進(jìn)來(lái)
- enhancer 是一個(gè)組合 store creator 的高階函數(shù),返回一個(gè)新的強(qiáng)化過(guò)的 store creator瞻坝。這與 middleware 相似,它也允許你通過(guò)復(fù)合函數(shù)改變 store 接口杏瞻。
enhancer ? (createStore) {
return function () {
var _console, _console2;
for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
args[_key2] = argum…
普及一下高階函數(shù)
高階組件就是一個(gè)函數(shù)所刀,且該函數(shù)接受一個(gè)組件作為參數(shù),并返回一個(gè)新的組件
// 高階組件 思想
function hello() {
console.log('我喜歡react');
}
function WrapperHello(fn) {
return function () {
console.log('before hello');
fn()
console.log('after hello');
}
}
var hello = WrapperHello(hello);
hello()
屬性代理
class Hello extends React.Component {
render() {
return <h2>高階組件的參數(shù)組件</h2>
}
}
function wrapperHello(Comp) {
class WrapComp extends React.Component {
render() {
return (<div>
<p>這是hoc高階組件特有的元素</p>
<Comp {...this.props}></Comp>
</div>)
}
}
return WrapComp
}
反向繼承
function wrapperHello(Comp) {
class WrapComp extends Comp{
componentDidMount(){
console.log('高階組件新增的生命周期捞挥,加載完成');
}
render(){
return <Comp></Comp>
}
}
return WrapComp
}
Hello = wrapperHello(Hello);
applyMiddleware源碼解讀
// 中間件機(jī)制
export function applyMiddleware (...middlewares) {
return createStore => (...args) => {
console.log(args)
// 這里的...args指的是解耦之后的renducer 在這里 指的就是counter
console.log(...args)
const store = createStore(...args)
let dispatch = store.dispatch
let midApi = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
// 單個(gè)中間件的情況
// dispatch = middleware(midApi)(store.dispatch)
// dispatch = middware(midApi)(stroe.dispatch)(action)
// 多個(gè)中間件的情況
console.log(store) // => store 就是一個(gè)對(duì)象 里面包含dispatch getState和subscribe等方法
console.log('middles', middlewares)
let middlewareChain = middlewares.map(middleware => middleware(midApi))
// 返回的這個(gè)dispatch 就執(zhí)行過(guò)了所有的中間件 帶有了中間件的功能
dispatch = compose(...middlewareChain)(store.dispatch)
return {
...store,
dispatch
}
}
}
compose函數(shù)源碼
function compose (...fns) {
if (fns.length === 0) {
return args => args
}
if (fns.length === 1) {
return fns[0]
}
// return fns.reduce((ret, item) => (...args) => ret(item(...args)))
return fns.reduce((ret, item) => (...args) => {
console.log('當(dāng)有多個(gè)參數(shù)的時(shí)候')
// ...args ==>> store.dispatch的這個(gè)方法 item和ret指代不同的中間件
/*
//假設(shè)
middleChain = [a,b,c]
dispatch = compose(...middlewareChain)(store.dispatch) = compose(a,b,c)(store.dispatch)
// 那么這個(gè)函數(shù)在compose中 就被拆解為
dispatch = compose(a(b(c)))(store.dispatch)
*/
return ret(item(...args))
})
}
結(jié)合中間件的源碼來(lái)看 我們這里以thunk舉例
- thunk中最開(kāi)始接受的參數(shù) {dispatch getState} 是從midApi中傳來(lái)的
- next 指代store.dispatch action就是action
const thunk = ({dispatch, getState}) => next => action => {
if (typeof action === 'function') {
// 如上面所示
return action(dispatch, getState)
}
// 默認(rèn)情況下
return next(action)
}
export default thunk
bindActionCreators 源碼解讀
官網(wǎng)用法 : http://www.redux.org.cn/docs/api/bindActionCreators.html
// 工具函數(shù) 這個(gè)函數(shù)的作用是為了讓creator函數(shù)里面的參數(shù)進(jìn)行透?jìng)?/*
addGun(參數(shù))
dispatch(addGun(參數(shù)))
*/
function bindActionCreator (creator, dispatch) {
return (...args) => dispatch(creator(...args))
}
// bindActionCreators
// {addGun, removeGun, addGunAsync} 就是形式參數(shù) creators
export function bindActionCreators (creators, dispatch) {
let bound = {}
Object.keys(creators).forEach((fnKey, index) => {
let creator = creators[fnKey]
bound[fnKey] = bindActionCreator(creator, dispatch)
})
return bound
/*
還可以采用另外一種寫(xiě)法
return Object.keys(creators).reduce((ret,item)=>{
ret[item] = bindActionCreator(creators[item],dispatch)
return ret
},{})
*/
}