博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
redux小记
阅读量:6929 次
发布时间:2019-06-27

本文共 6822 字,大约阅读时间需要 22 分钟。

先看看几个异步处理方式:

  callback:传入一个回调函数,在未来某个不确定的时间点调用,想要控制异步的调用顺序,需要加入很多变量和代码逻辑,引发‘回调地狱’。

  thunk:是一种你无需你传入任何参数就可以正常工作的函数,如果你想获取其中的值,则需要传入一个回调函数。thunk 把时间的概念抽象出去的,执行 thunk 函数后,我们只需要等待结果就行,无需去关心内部是什么,做了什么事情,需要花费多少时间。thunk 的本质其实是使用闭包来管理状态。

  Promise:核心在于其通过一种协议[4]保障了then后注册的函数只会被执行一次。这和上面提到的回调不同,普通的 callback 实际上是第三方直接调用我们的函数,这个第三方不一定是完全可信的,我们的回调函数可能会被调用,也可能不会调用,还可能会调用多次。

        缺点:一旦开始执行就没办法手动终止;

           我们无法完全捕获可能的错误。比如说 .catch 中的错误就难以再被捕获;

  Generator:把我们的代码分割成了独立可阻塞的部分,局部的阻塞不会导致全局的阻塞,需要我们手动调用 .next()来继续执行后面的内容。我们完全不知道谁会在什么地方调用.next(),结合 Promise 我们可以比较轻松的解决「控制反转」的问题,一些人把 Promise + Generator 当作是异步最好的解决方案之一。

  async await:和generator类似,async 函数只有在结束时,才会返回的是一个 Promise。我们无法控制其中间状态,而 generator 返回的是迭代器,迭代器让你有充分的控制权。

 

Redux 设计和使用的三大原则:

  1. 单一数据源:

    一个应用永远只有唯一的数据源。使用单一数据源的好处在于整个应用状态都保存在一个对象中,这样我们随时可以 6提取出整个应用的状态进行持久化(比如实现一个针对整个应用的即时保存功能)。此外,这样 的设计也为服务端渲染提供了可能。工具函数combineReducers 可解决该数据源对象过于庞大的问题

    combineReducers 的返回 值是一个归一 化的 rootReducer 函数 。 也就是说, combineReducers作为一个函数,它返回了另一个函数( rootReducer)。“函数返回一个新的函数”,这就是函数式编程的典型思想。 combineReducers 返回的函数就是 一个标准的 reducer,它的参数接收 state 和action

    const combineReducers = (reducers) => {

      return (state={} , action) => {

        return Object.keys(reducers) .reduce(

          (nextState , key) =>

            nextState [key] = reducers [key] (

              state [key] ,

              action

            );

            return nextState;

          },

          {}

        );

      }

    }

  2. 状态是只读的:

    定义一个 reducer, 它的功能是根据当前触发的 action 对当前应用的状态(state)进行迭代,这里我们并没有直接修改应用的状态,而是返回了一份全新的状态。Redux 提供的 createStore 方法会根据 reducer 生成 store。最后,我们可以利用 store. dispatch方法来达到修改状态的目的。

  3. 状态修改均由纯函数完成

    Redux 利用每次新返回的状态生成酷炫的时间旅行(time travel)调试方式,让跟踪每一次因为触 发 action 而改变状态的结果成为了可能。

 

通过 createStore 方法创建的 store 是一个对象,包含以下方法。

 getState():获取 store 中当前的状态。

 dispatch(action):分发一个 action,并返回这个 action,这是唯一能改变 store 中数据的方式。

 subscribe(listener):注册一个监听者,它在 store 发生变化时被调用。  

 

<Provider/> 接受一个 store 作为props,它是整个 Redux 应用的顶层组件,而 connect() 提供了在整个 React 应用的任意组件中获取 store 中数据的功能。

  

redux-middleware:

  import compose from './compose';

  

  let newStore = applyMiddleware(mid1, mid2, mid3, ...)(createStore)(reducer, null);//创建一个普通的 store

  export default function applyMiddleware(...middlewares) {//applyMiddleware 的结构也是一个多层 currying 的函数。借助 compose,applyMiddleware 可以用来和其他插件加强 createStore 函数:

    return (next) => (reducer, initialState) => {

      let store = next(reducer, initialState);//利用 createStore 和 reducer 创建了一个 store

      let dispatch = store.dispatch;

      let chain = [];

      var middlewareAPI = {

        getState: store.getState,
        dispatch: (action) => dispatch(action),

      };//store 的 getState方法和 dispatch 方法又分别被直接和间接地赋值给 middlewareAPI 变量 store

      chain = middlewares.map(middleware => middleware(middlewareAPI));//middleware 带着 middlewareAPI 这个参数分别执行一遍。执行完后,获得 chain数组,保存的对象是第二个箭头函数返回的匿名函数

      dispatch = compose(...chain)(store.dispatch);//将 chain 中的所有匿名函数,组装成一个新的函数,即新的 dispatch。当新 dispatch 执行时,数组内middleware从右到左依次执行

      return { ...store,

          dispatch,

      };

    }

  }

 

  logger middleware 的实现:

  export default store => next => action => {//applyMiddleware 会对 logger 这 个 middleware 进行层层调用,动态地将 store 和 next 参数赋值。

    console.log('dispatch:', action);

    typeof action === 'function' ? action(store.dispatch, store.getState) : next(action)//判断 action 是否是函数。如果是,则执行 action,否则继续传递 action 到下 一个 middleware。

    console.log('finish:', action);

   }

 

  redux-saga: 采用generator,代替了async、await、promise等

 

  react-router-redux:

    对于前端应用来说,路由状态(当前切换到了哪个页面,当前页面的参数 有哪些,等等)也是应用状态的一部分。在很多情况下,我们的业务逻辑与路由状态有很强的关 联关系。比如,最常见的一个列表页中,分页参数、排序参数可能都会在路由中体现,而这些参 数的改变必然导致列表中的数据发生变化。因此,当我们采用 Redux 架构时,所有的应用状态必须放在一个单一的 store 中管理,路由 状态也不例外。而这就是 React Router Redux 为我们实现的主要功能。

    对 Redux 的 store 进行一些增强,以便分发的 action 能被正确识别

    

    import { browserHistory } from 'react-router';

    import { routerMiddleware } from 'react-router-redux';

    const middleware = routerMiddleware(browserHistory);

    const store = createStore(

      reducers,

      applyMiddleware(middleware)

    );

    

    可以用 store.dispatch 来分发一个路由变动的 action 了:

    import { push } from 'react-router-redux';

    // 切换路由到 /home store.dispatch(push('/home'));

 

高阶 reducer 主要通过下面 3 点来增强reducer:高阶 reducer 就是指将 reducer 作为参数或者返回值的函数

 能够处理额外的 action;

 能够维护更多的 state;
 将不能处理的 action 委托给原始 reducer 处理。

createStore 的函数签名:

export default function createStore(reducer, initialState, enhancer) { // ...}

createStore 中的第二个参数不仅扮演着 initialState 的角色。如 果我们传入的第二个参数是函数类型,那么 createStore 会认为你忽略了 initialState 而传入了 一个 enhancer。

如果我们传入了一个有效的enhancer,createStore会返回enhancer(createStore)(reducer, initialState) 的调用结果,这是常见的高阶函数调用方法。在这个调用中,enhancer 接受createStore 作为参数,

对 createStore 的能力进行增强,并返回增强后的 createStore。然后再 将 reducer 和 initialState 作为参数传给增强后的 createStore,最终得到生成的 store。

var currentReducer = reducer

var currentState = initialState

var listeners = []

var isDispatching = false

function getState() {

  return currentState//getState 方法用于返回当前状态。

}

const dispatch = (action) => {

  state = currentReducer(state, action );

  listeners . forEach(listener =>listener( ));

}

const subscribe = (listener) => {

  listeners .push(listener);

  //返回一个函数 , 进行取消 订 阅

  return () => listeners = listeners filter (item =>工 tern!== listener) ;

}

return { getState , dispatch , subscribe };

dispatch---将当前的状态和 action 传给当前的reducer,用于生成最新的 state。在得到新的状态后,依次调用所有的监听器,通知状态的变更。

需要注意的是,我们在通知监听器变更发生时,并没有将最新的状态作为参数传递给这些监听器。这是因为在监听器中,我们可以直接调用 store.getState() 方法拿到最新的状态。

 

React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)。

React-Redux 提供connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来。

connect 函数本身返回名为 wrapWithConnect 的函数,而这个函数才是真正用来 装饰 React 组件的。而在我们装饰一个 React 组件时,

其实就是把组件在 Connect 类的 render 方 法中进行渲染,并获取 connect 中传入的各种额外数据。

connect 函数如果传入mapStateToProps,则会store.subscribe()监听state变化

connect ( mapStateToProps ,mapDispatchToProps,mergeProps,options) 

在 options 中,支持自定义 areStatesEqual 函数,以便进行前后两次 state 比较。 areStatesEqual函数接收两个参数,第一个是前一个 state,第二个是后一个 state。 如果该函数的返回值为 true,那么 mapStateToProps 方法便不再执行,因为规避了不必要的渲染 。

 

Provider在根组件外面包了一层,这样一来,App的所有子组件就默认都可以拿到state了。它的原理是React组件的属性

class Provider extends Component {

  getChildContext() {

    return {store: this.props.store}

  }

  render() {

    return this.props.children;

  }

}

子组件就可以从context拿到store

 

createSelector:

export default createSelector(

  allitemsSelector ,

  selectedidSelector ,

  getItems

)

createSelector函数可以接收多个参数,最后一个参数要保证为计算最终 state片段的规则函数,前面所有参数的计算结果都会作为计算所需的 state片段,传入最后一个参数中进行计算。createSelector( ... inputSelectors I [ inputSelectors] , resultFunc )当 Redux state变化时, al!ItemsSelector和 selectedldSelector都会执行,当它们的返回结果发生变化时, getltems 将会自动计算出最新的己选择条目。

当前后两次 inputs巳lectors (即 allitemsS巳lector和 selectedldSelector)计算所得结果没有发生变化时, resultFunc (即 getltems)将会直接返回缓存结果,因而规避了大量的计算

开销。

  

转载于:https://www.cnblogs.com/diyigechengxu/p/10895135.html

你可能感兴趣的文章
c语言中有bool型变量吗?
查看>>
Null值的使用
查看>>
《程序设计与数据结构》 课程教学
查看>>
注册asp.net
查看>>
java.net.ProtocolException: Exceeded stated content-length of: '13824' bytes
查看>>
详解Spring事件驱动模型
查看>>
内存分配有哪些策略
查看>>
WebView与JS的几种交互
查看>>
ffmpeg去logo<转>
查看>>
下载Tomcat时Tomcat网站上的core和deployer的区别
查看>>
imx6 关闭调试串口
查看>>
easyUi datagrid 返回时间格式化操作
查看>>
redis.conf配置详细翻译解析
查看>>
Linux Nano命令
查看>>
线程高级应用-心得4-java5线程并发库介绍,及新技术案例分析
查看>>
linux 弹出光驱失败
查看>>
grep用法详解:grep与正则表达式【转】
查看>>
Python中执行系统命令常见的几种方法--转载
查看>>
spring整合springmvc
查看>>
【译】Kafka学习之路
查看>>