Immutable.js

作者: 雪牙那个前端 | 来源:发表于2016-05-05 18:00 被阅读1760次

    Immutable.js在react + router + redux项目中的应用

    先介绍一下Immutable:

    Immutable.js的出现源于Functional Programming的思想,即所有数据应该是复制过来,而不是直接修改。相关介绍看它官网:
    https://facebook.github.io/immutable-js/

    所以如果你有一些编程经验,可以理解为Immutable就是另外一个数据结构的库。就好像从ArrayList换成LinkedList一样。在Immutable.js下,就是从JavaScript语法自有的Array(就是[])和Object{ }),换到Immutable.ListImmutable.Map了。

    但是ArrayListLinkedList毕竟都继承于List,接口上比较一致,换起来问题不大,但是想用Immutable换JavaScript原生,就要略复杂些。

    var map1 = Immutable.Map({a:1, b:2, c:3});
    var map2 = map1.set('b', 50);
    map1.get('b'); // 2
    /* ----------------悠长悠长的分割线---------------- */
    var list1 = Immutable.List.of(1, 2);
    var list2 = list1.push(3, 4, 5);
    var list3 = list2.unshift(0);
    var list4 = list1.concat(list2, list3);
    

    复杂归复杂,不过是多注意一点吧。

    然后要说到redux和router

    Redux有一个combineReducers方法,可以做到Reducer的拆分。比如:

    combineReducers({
      user: userReducer,
      dashboard: dashboardReducer,
    })
    

    那么问题来了:
    当你获取state的时候,你是用state.get('user')还是用state.user

    显然要用state.user。因为combineReducers不认识Immutable啊。
    (不要告诉我混用,一层结构可以这样,多层呢?多人合作呢?一处蒙逼,处处报错啊)

    所以如果你想在一个react + router + redux的项目下用Immutable,要么就局部使用(局部的话,基本会很nightmare吧),要么就换全套的。
    然后就是看这里(这哥们把combineReducers给重新写了):
    https://github.com/gajus/redux-immutable

    用他们家的combineReducers,你就可以放心地用state.get('user')

    在解决combineReducers的同时,他们家还顺带解决了react-router-redux的问题(试想router作为state下的routing模块却不懂用Immutable该多呵呵):

    https://github.com/gajus/redux-immutable#using-with-react-router-redux

    说了这么多,怎么用呢

    首先你的项目是react + router + redux的标配。
    然后你要引入Immutable。

    那么你该这样:

    1. 引入redux-immutable
    2. 按照redux-immutable的README.md把history什么的配置好(Ctrl+C, Ctrl+V)
    3. 所有reducer合并的时候换用redux-immutable的combineReducers
    4. 所有数据出入state用Immutable.js的Immutable.ListImmutable.Map(这个才是正题)

    还有什么要注意的吗?

    组件的问题:

    从redux过来的思想是把组件分成Smart和Dumb。Smart组件负责把数据接进来,Dumb组件负责使用数据,并只关注props。所以Immutable要覆盖Smart和Dumb吗?

    我个人观点是这样的:
    Dumb组件基本都是要抽象出来给多个项目共用的。这部分组件不支持Immutable应该更好些,否则就被绑死在Immutable上了。

    那这么说,Dumb里的数据是JavaScript原生的,岂不是享受不到Immutable带来的好处?
    数据已经复制给了组件,为了兼容性牺牲一点这个也没啥吧?

    这个想法背后的结论就是:
    redux概念里的Container在做state与props之间,props与dispatch之间的对接的时候,也同时做了Immutable与原生的相互转换。(Adapter Pattern吧)

    测试的时候:

    你会想console.log一下当前的数据吧,把Immutable.List打出来看着很累的,建议用console.log(imtb.toJS())

    可是debug的时候呢?

    题外话

    如果这些特性是JavaScript本身内置的就好了。

    相关文章

      网友评论

      • e9f83a8b2f66:我试了一下,Immutable.List , 和 Map ,他们都不能处理js 数组,object 嵌套的情况,
        地址: https://github.com/duanbowen/how-to-start-react/blob/master/immutable-api/src/map.js
      • smartphp:redux的思想是把组件和交互的具体逻辑分开,若果是简单分就是 dumb component<–>connect<–>redux. 为了解决复杂逻辑下的state的处理,把action 和action 逻辑解耦合。木偶组件之执行交互操作的动作,具体的操作导致的state
        的改变全部在redux中完成,所以导入immutable.js主要是解决redux中操作state的效率问题。 所以木偶组件之看到state,至于是assign或者immutable.js处理的stat木偶组件是不知道的。

        这个理解不知道对不对?

      本文标题:Immutable.js

      本文链接:https://www.haomeiwen.com/subject/evbdrttx.html