Redux解读

tip01 概念&原理

      Redux类似Vue中的Vuex, 在复杂的应用中改变react.js更新数据的方式,并实现统一数据管理的方式。应用较简单时真的不需要使用Redux, 考虑整个团队的技术水平以及熟悉的技术栈,适合自己的才是最好的!

       使用Redux管理状态,流程的简单描述(摘自 https://www.redux.org.cn/):应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中。 惟一改变 state 的办法是触发 action,一个描述发生什么的对象。 为了描述 action 如何改变 state 树,你需要编写 reducers。我的理解是:通过dispatch传入action信号(“吃啥” “喝啥” “怎么买”)然后触发reducer("自己买" 还是 “外卖”,还是“DIY”), 熟悉Vuex的同学也可以看作是Vuex中的 mapMutations或者mapActions的作用, 而这一切的操作,专业点说是api或者方法的提供者便是 store ,  他来自于火星 createStore,  名叫redux的火星  import { createStore } from 'redux'; const store = createStore(fn); 

tip02 深入源码看原理

        createStore到底是一个什么?“哎呀就是一个函数了 ,接受三个参数,分别是 reducer, preloadedState, enhancer”, 好不耐烦的样子,就像产品经理和你讲这个改下交互方式吧,为什么,“嗯。。。。嗯。。客户需求吧”, 好的,滚!!!!一个不能说服前端的产品不是一个好UI。

源码解析:

 

 1 export default function createStore(reducer, preloadedState, enhancer) {
 2   if (
 3     (typeof preloadedState === 'function' && typeof enhancer === 'function') ||
 4     (typeof enhancer === 'function' && typeof arguments[3] === 'function')
 5   ) {
 6     throw new Error(
 7       'It looks like you are passing several store enhancers to ' +
 8         'createStore(). This is not supported. Instead, compose them ' +
 9         'together to a single function.'
10     )
11 }
12 ......

 

 

 

 createStore的三个参数,其中最常用的是第一个  reducer, 职责:数据加工(通过dispatch根据不同的action指示,执行不同的reducer,产生不同的数据)

                   preloadedState, 职责:数据的预渲染,可以看作初始化数据

                     enhancer, 职责:拓展功能的函数

createStore的返回值

getState:  源码片段 

 1 function getState() {
 2     if (isDispatching) {
 3       throw new Error(
 4         'You may not call store.getState() while the reducer is executing. ' +
 5           'The reducer has already received the state as an argument. ' +
 6           'Pass it down from the top reducer instead of reading it from the store.'
 7       )
 8     }
 9 
10     return currentState
11   }

 其作用就是返回一个state(redux管理下的数据),确切说是当前store中的state tree,其中 isDispatching是一个判断值:判断dispatch是否在执行,因为redux中为了保证数据更新的顺序性,杜绝bug,在数据处理期间不能获取数据。

subscribe:源码片段
 1 function subscribe(listener) {
 2     if (typeof listener !== 'function') {
 3       throw new Error('Expected the listener to be a function.')
 4     }
 5 
 6     if (isDispatching) {
 7       throw new Error(
 8         'You may not call store.subscribe() while the reducer is executing. ' +
 9           'If you would like to be notified after the store has been updated, subscribe from a ' +
10           'component and invoke store.getState() in the callback to access the latest state. ' +
11           'See https://redux.js.org/api-reference/store#subscribelistener for more details.'
12       )
13     }
14 
15     let isSubscribed = true
16 
17     ensureCanMutateNextListeners()
18     nextListeners.push(listener)
19 
20     return function unsubscribe() {
21       if (!isSubscribed) {
22         return
23       }
24 
25       if (isDispatching) {
26         throw new Error(
27           'You may not unsubscribe from a store listener while the reducer is executing. ' +
28             'See https://redux.js.org/api-reference/store#subscribelistener for more details.'
29         )
30       }
31 
32       isSubscribed = false
33 
34       ensureCanMutateNextListeners()
35       const index = nextListeners.indexOf(listener)
36       nextListeners.splice(index, 1)
37       currentListeners = null
38     }
39   }
这个方法主要任务是:当一个dispatch出发了action之后,进行一次监听,根据新的state更新视图,然后释放。

其中
ensureCanMutateNextListeners 方法是确保下次的监听队列是最新的,最齐全的队列,实质是把当前的队列浅拷贝给了下次的队列,源码如下:注意slice的用法
function ensureCanMutateNextListeners() {
    if (nextListeners === currentListeners) {
      nextListeners = currentListeners.slice()
    }
  }

接着 nextListeners.push(listener) ,添加新的监听,在 subscribe 最后,返回一个  unsubscribe 方法 :释放监听对象,清空整个队列。

重中之重的 dispatch 源码片段

 1 function dispatch(action) {
 2     if (!isPlainObject(action)) {
 3       throw new Error(
 4         'Actions must be plain objects. ' +
 5           'Use custom middleware for async actions.'
 6       )
 7     }
 8 
 9     if (typeof action.type === 'undefined') {
10       throw new Error(
11         'Actions may not have an undefined "type" property. ' +
12           'Have you misspelled a constant?'
13       )
14     }
15 
16     if (isDispatching) {
17       throw new Error('Reducers may not dispatch actions.')
18     }
19 
20     try {
21       isDispatching = true
22       currentState = currentReducer(currentState, action)
23     } finally {
24       isDispatching = false
25     }
26 
27     const listeners = (currentListeners = nextListeners)
28     for (let i = 0; i < listeners.length; i++) {
29       const listener = listeners[i]
30       listener()
31     }
32 
33     return action
34   }

是不是看着很吓人,其实两句话的事,不,是一句话:根据不同的action执行不同的redreucer后遍历监听事件!完事!!!其实大概看过node Event原理的童鞋看这个并不难,本质就是事件执行后,通知队列池,依次执行池子里的监听事件,这里只不过是reducer后执行listener的,而currentReducer就是整个redux的数据处理中心,涵盖了所有reducer,根据不同的action指示进行数据处理,处理后的数据返回给 currentState。 dispatch方法只接受一个参数 action, 一个通过type作为标识的对象,具体用法参考官网 https://www.redux.org.cn/docs/basics/Actions.html ,这里只对原理源代码进行解释说明,明白原理,相信你才能更好的驾驭他。

 

下一篇解读第一个参数 reducer 以及 combineReducers!

 

 

下一篇:createStore第一个参数reducer

 

 

 

 




















posted @ 2020-03-02 10:36  前端怎么着你了  阅读(398)  评论(0编辑  收藏  举报