资讯专栏INFORMATION COLUMN

Redux story-1:who creates it?

lavor / 1003人阅读

摘要:而不是卷入无休止的撕逼,用了某某而产生的优越,甚至借贬低他人来抬高自己。

前言

 这是一个系列文章,旨在分享在react及相关技术栈实践过程中的个人感悟,心得。如果有不好的地方,欢迎各位批评指正。

 由于对react本身还未深入了解,今天我们先来谈一谈redux相关的问题。

Who creates it?

 Dan Abramov是redux的作者,同时,他也是Create React App, React Hot Loader作者。当然1年前,他也由于redux及相关的开源贡献加入了facebook(他大二就辍学了,之前还当过.net工程师)。

 在我最初了解到他的时候,我觉得他非常有礼貌。同时,也为了更多的了解redux,我计划开始阅读他的每一条tweet,原先计划的是从15年7月开始,后来因为进展缓慢,而且react版本也已经发生很大变化了,于是便从16年1月1日开始阅读,目前记录到7月15日了。事实也证明,在这个过程中,的的确确学习到了很多东西。包括redux的文档及redux-links的作者Mark Erikson,以及国外很多写过redux系列的朋友们。

 如果你有兴趣的话,可以看看我摘录的一些片段。其中除了知识性的内容外,还有一些关于它自己生活,经历,学习方法,如何面对JS疲劳等等的摘录。也让我渐渐的了解到了国外的程序员们的一些观点,兴趣,梗等等。

正文

 好了,暂时先介绍到这里了。切回redux本身,下面是学习源码过程中自己的一些体会。

createStore

createStore的第3个参数为enhancer,如果enhancer有多个,那么应该使用compose的方式组合多个enhancer

 且每个enhancer的模板为export default createStore => (reducer, preloadedState, enhancer) => {...}

 因为在createStore中执行了:return enhancer(createStore)(reducer, preloadedState)

 另外,上面的提到的形如(reducer, preloadedState, enhancer) => {...} 这个样子的其实都可以叫做createStore

 这也是社区有那么多enhancer的原因,他们可以形成一个enhancer链,我调用你的createStore,然后返回我的createStore供下一级调用

 所以在自己的createStore的函数体中经常能看到诸如var store = createStore(reducer, preloadedState, enhancer);这样的用法,目的就是让自己这一级之前的enhancer产生一个store出来,而之前的enhancer里的createStore又会调用之前的,到最尽头,就是redux本身的createStore

applyMiddleware

applyMiddleware的目的是返回一个enhancer,这个enhancer存储了1个或者多个中间件,中间件在上一级的dispatch方法的基础上增添自己的逻辑,然后返回自己的dispatch方法

 对于中间件而言,中间件的模板为:export default store => next => action => {...}。有的地方也写成export default _ref => next => action => {...}或者export default ({getState, dispatch}) => next => action => {...},看自己喜好了

 实际的调用顺序如下(定义在reduxapplyMiddleware.js中):

1. middleware(middlewareAPI);
/*
    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    };
    
    chain = middlewares.map(middleware => middleware(middlewareAPI));
    dispatch = compose(...chain)(store.dispatch);

    第1步即为第1次执行中间件,用redux自己的dipatch初始化各个中间件里的dispatch(也就是中间件的next参数)和getState。
    从而确保至少redux本身能够正常工作,中间件的store或者_ref即为这里的middlewareAPI
* */

2. dispatch = compose(...chain)(store.dispatch);
/*
    第2步即为第2次执行中间件
    即用compose的形式链式调用第1步返回的中间件集合,如果中间件是定义在applyMiddleware的最后一个
    那么中间件里的next为store.dispatch,否则next为上一个中间件返回的结果,可以理解为上一个中间件
    返回的是封装了dispatch的自己的dispatch,这里的原理其实和enhancer一模一样

    enhancer的目的是封装多次createStore并用compose的方式进行调用
    middleware的目的是封装多次dispatch并用compose的方式进行调用
* */

总结:
/*
    所以最后在redux的createStore.js中return的enhancer(createStore)(reducer, preloadedState)的结果就是一个增强
    版的store,而这个增强版的store中存放的是增强版的dispatch
* */

/* ××××××××××××××××关于combineReducers×××××××××××××××
*   从执行上来说,combineReducers实际上最后就是变成对reducers进行深度优先遍历并执行的过程
*   从结构上来说,combineReducers决定了我们的state状态树的最终结构或者说形状,他是呈一个树型结构的
*   combineReducers(reducerA, reducerB),reducerA里面嵌套combineReducers(reducerA-child1, reducerA-child2)
*   实际上对应状态树而已就是第一层有两个节点A,B,而A节点下面有两个子节点A-child1,A-child2
*
*   所以在最初设计的时候,我们要设想我们最终的状态树的样子,然后合理划分reducer,就像设计数据库的表结构一样。
    当然这是比较概括的说法,事实上reducer的设计或者说state的划分有太多太多值得研究的东西,这个我们以后再谈了。
* */
bindActionCreator

bindActionCreator实际就是给actionCreator外层再添加了一层函数,而这层函数存放了对dispatch的引用

function bindActionCreator(actionCreator, dispatch) {
  return (...args) => dispatch(actionCreator(...args))
}

所以我们可以一般在组件里直接调用bindActionCreator返回的actionCreator,即this.props.loadSomething(...)。而不用写成dispatch(actionCreator(...args)),实际上他们是等价的

connect

 既然提到了redux,由于目前我是采用react进行开发,所以不得不提到相关的react-redux。其中最重要的莫属于connect这个函数了。

 传入connect的组件在挂载到页面上后会调用store.subscribe进行订阅,订阅的目的是我们调用dispatch的时候,表明我们的状态树即将发生变化,这个时候我们希望我们的组件对应发生变化,而组件变化的唯一方式就是setState

 订阅就是告诉redux,这个组件是依赖于状态树的某部分工作的,所以当你变化的时候,记得获取最新的state,然后通知我,至于我如何响应,那就是我自己的事了,你只管通知我状态树发生了变化并把它传给我就行了。值得一提的是,connect内部进行了大量的性能优化,避免不必要的渲染,关于此以及mapStateToPropsmapDispathToProps,我们放到以后再谈。

结语

 篇幅有限,这一篇文章暂时就先这样啦,更多的内容,我想放在下一篇来分享,同时自己也在不断学习,希望能理解得更好。

 值得一提的是,我们也许会认为我们了解到的redux,mobx,rxjs等等完全不同理念的库,他们的作者也许也是"极端"的,是排斥他人及理念的。实际上,这是不正确的,早在16年5月,Dan就和mobx的作者在twitter上有过互动,他们达成了共识,那就是和对方一起合作,一起推动自身以及react的发展。

 对于redux-thunk,文档中也许会首先建议使用这个简单的库来处理异步相关的问题。对于复杂的应用,他们也推荐使用redux-saga这样的库去重构自己的代码。在twitter上,Dan也多次提到过库的应用场景的问题,建议大家用之前先了解自己为什么要使用,它解决了哪些痛点,然后再去使用。甚至特意提过issue,来了解react-router-redux的作用。

 除此之外,也提到在时间充裕的情况下,学习react,应该先从本身入手,ES6,webpack,jsx,redux等等和react本身都是没有直接联系的,在学习完react之后,我们知道了他本身的哪些不足,哪些地方需要加强,哪些地方需要引入第三方库去解决,解决的是哪些痛点,我们再去了解这些工具,才能真正体会到他们的威力。

 说到这里,稍微有一点远了,不过我觉得还是有必要提及一下。那就是,我们身处一个浮躁的社会,无论是在现实中对待朋友,亲人,陌生人,由于学习,工作,生活的压力,周遭的浮躁氛围的影响,多多少少也会让自己带着些许暴戾之气。在网络上,由于约束的放宽,我们也许更会将压抑的情感释放给广袤的网络世界,在微博,贴吧,知乎上,我们或多或少书写着,察觉着这样的行为。

 但是,作为一名程序猿,我还是期待能够看到我们这个圈子更多的将时间,精力,努力花费在对现有技术的改进,对未知世界的探索,追寻程序,库,框架,思想的本质,结交志同道合的朋友,一起交流,分享,思考对技术的看法。而不是卷入无休止的撕逼,用了某某而产生的优越,甚至借贬低他人来抬高自己。

 我们可以理解一时的愤懑之情,因为我们大多,真是只是普普通通的社会人,喜怒哀乐再平常不过。但若我们一直保持这种状态,永远在上面这些场景都留下对人不对事的话语,讥讽,甚至谩骂。希望大家能为我们的后代想想。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/81288.html

相关文章

  • react-redux-antd项目搭建

    摘要:因为是想搭建一个后台系统,所以组件直接定了,脚手架以为基准,加上和因为我一直用的这次换个口味搭建一个简单的项目。 因为是想搭建一个后台系统,所以组件直接定了antd,脚手架以create-react-app为基准,加上redux和sass(因为我一直用的less,这次换个口味),搭建一个简单的项目。 安装依赖 首先安装create-react-app npm i create-reac...

    王陆宽 评论0 收藏0
  • reduxcreateStore的源码,带中文翻译

    摘要:只有在你需要实现代码分隔,而且需要立即加载一些的时候才可能会用到它。 import isPlainObject from lodash/isPlainObject import $$observable from symbol-observable /** * These are private action types reserved by Redux. * For any ...

    tanglijun 评论0 收藏0
  • redux 源码阅读笔记

    摘要:函数用于为应用的状态添加监听,以一个回调函数监听函数为参数当触发时执行所有监听函数,返回能够取消订阅的函数。函数用于组合多个中间件返回的函数,其实质是生成新的暴露给用户。 redux 源码阅读笔记 redux 中的 reducer 为什么要叫这个名字?(UPDATED) 笔者在学习 redux 的时候一直感觉 reducer 很不好理解(非要进行翻译的话,可以称之为缩减器/折叠器),而...

    魏宪会 评论0 收藏0
  • 你想要的——redux源码分析

    摘要:大家好,今天给大家带来的是的源码分析首先是的地址点我接下来我们看看在项目中的简单使用,一般我们都从最简单的开始入手哈备注例子中结合的是进行使用,当然不仅仅能结合,还能结合市面上其他大多数的框架,这也是它比较流弊的地方首先是创建一个首先我们 大家好,今天给大家带来的是redux(v3.6.0)的源码分析~ 首先是redux的github地址 点我 接下来我们看看redux在项目中的简单使...

    enrecul101 评论0 收藏0
  • 前端单元测试探索

    摘要:单元测试的首要目的不是为了能够编写出大覆盖率的全部通过的测试代码,而是需要从使用者调用者的角度出发,尝试函数逻辑的各种可能性,进而辅助性增强代码质量测试是手段而不是目的。 本文已发布在稀土掘金 转载请注明原文链接:https://github.com/ecmadao/Co... 虽然很多公司有自己的测试部门,而且前端开发大多不涉及测试环节,但鉴于目前前端领域的快速发展,其涉及面越来...

    陈江龙 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<