V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yesvods
V2EX  ›  React

滚蛋吧! constant 君

  •  1
     
  •   yesvods ·
    yesvods · 2015-11-24 09:33:15 +08:00 · 2669 次点击
    这是一个创建于 3294 天前的主题,其中的信息可能已经有所发展或是发生改变。

    前言

    事情经过是这样的,某个阳光明媚的晚上,跟大多数人一样,在 MacBook 前静静地写着 redux/flux “优美”的诗句。剧情急转直下:

    └── constants
        ├── comA.js
        ├── comB.js
        ├── comC.js
        ├── comD.js
        ├── comE.js
        └── index.js
    

    index.js 看起来是这样的:

    import * from './a';
    import * from './b';
    ...
    

    好像没什么不对劲,然后看了一下 a.js 和 b.js..

    //a.js
    export const OPEN_SIDEBAR = "OPEN_SIDEBAR";
    export const CLOSE_SIDEBAR = "CLOSE_SIDEBAR";
    export const HIDE_ITEM = "HIDE_ITEM";
    
    //b.js
    export const TOGGLE_LIST = "TOGGLE_LIST";
    export const CHANGE_WIDTH = "CHANGE_WIDTH";
    export const HIDE_ITEM = "HIDE_ITEM";
    

    。。
    。。。
    。。。。

    喵的,不同组件的 constant 又写重复了。于是开始漫长的改 constant 之旅:

    • 名字改成 COMB_HIDE_ITEM
    • reducers/comB.js 改几个 store/reducer
    • actions/comB.js 改几个 action

    慢着....
    好像 comC,comD,comE 都有这个 constant

    问题由来

    咳咳,膝盖中箭的有木有,站出来!其实 constant 这个常量在 react 界最先被 flux 框架采用,再后来著名的redux( star 数已经超过 flux ),也采用同样方式定义 action 与 reducer 之间的事件分发机制。引入 constant ,有效解决事件分发时,事件类型的一致性以及清晰逻辑性。

    constant 的悲惨经历

    其实一直以来,业界津津乐道的是react 的 vm,flux/redux 的状态管理机制webpack 开发技巧以及插件使用react-router 入门 etc.

    constant 如此重要的事件结构机制因为可将性太低,往往被大家忽略。其实,细心思考,不难发现,随着项目增大。 constants 目录将会随着数据处理事件迅速膨胀。大家一直维护着这个事件命名机制,身心疲惫有木有。

    constant 发展

    constant 由一开始的 flux 风格,配合 facebook 插件库

    export KeyMirror({
        ADD_TODO: null,
        COMPLETE_TODO: null,
        SET_VISIBILITY_FILTER: null
    })
    

    再到小项目维护的 constant ,非常容易导致重复

    export const ADD_TODO = 'ADD_TODO'
    export const COMPLETE_TODO = 'COMPLETE_TODO'
    export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER'
    

    引用redux 文档的原话:

    Types should typically be defined as string constants.
     Once your app is large enough, 
     you may want to move them into a separate module.
    

    看到刚刚 LZ 的经历,大家可以发现。其实, constant 随着项目增大,独立出来的 constants 也会导致非常麻烦的维护问题。

    constant 的进化

    类似constant-mirrorflux-constants的库都耐不住寂寞了,站出来声张正义。
    但是,这些库其中一个致命共同点:
    - 我们都依旧需要维护一套 constants
    - 不同组件使用的 constants 依旧有可能会因为重复导致不可预知的问题

    react-constant

    简介

    就一句话:

    Fuck off constants.js
    

    我们再也不需要去维护任何的与 constant 有关的文件,也不需要到处去找constants/comA.jsreducer/comA.jsaction/comA.js一个个去改命名。

    • 把所有 constant 相关文件去掉, react-constant 为您打理得井井有条
    • 自定义命名空间的 constant , comA 的HIDE_ITEM和 comB 的HIDE_ITEM可不一样,自家用自家的,互不侵犯。
    • 自动生成伪 uuid 格式的 constant ,不用再为生成格式打个 null
    • 2kb 大小( minified ),任何地方的贴心小助手
    • 单元测试, 100% coverage

    使用过程相当简单,没有任何多余的代码

    Usage

    Install

    npm install react-constant --save
    

    Import & Instance

    Webpack/Browserify

    //ES5 version
    var Constant = require('react-constant').Constant;
    var constants = Constant('mynamespace');
    
    //ES6 version
    import { Constant } from 'react-constant';
    let constants = Constant('mynamespace');
    

    browser

    <script src="dist/constant.min.js"></script>
    

    Just do it

    reducer.js

    function reducer(state, action){
      switch(action.type){
      case constants.of('ON'):
        //TODO
        break;
      case constants.of('OFF'):
        //TODO
        break;
      default: 
        return state;
      }
    }
    

    action.js

    function toggleLight(flag){
      return {
        type: constants.ON,
        flag: flag
      }
    }
    

    最后卖个过白,欢迎大家 follow 我的Github,后续会有更多精彩文章以及开源项目与大家共享,欢迎大家交流讨论。

    6 条回复    2016-01-06 16:29:40 +08:00
    scarlex
        1
    scarlex  
       2015-11-24 10:09:16 +08:00
    支持,占了 react-* 这个坑就好好维护下去
    iwege
        2
    iwege  
       2015-11-24 10:20:26 +08:00
    你前面加一个模块自己的 namespace 不就好了么?
    yesvods
        3
    yesvods  
    OP
       2015-11-24 13:45:22 +08:00
    @iwege 有两个问题,一来,会导致模块命名太长,妨碍阅读以及编码。依旧需要自己维护很多个相关的文件,非常麻烦。
    yesvods
        4
    yesvods  
    OP
       2015-11-24 13:52:12 +08:00   ❤️ 1
    @scarlex 谢谢,同是广州几乎同龄,倍感亲切啊
    zhuangzhuang1988
        5
    zhuangzhuang1988  
       2015-12-27 23:13:50 +08:00
    我想到的是 2 个解决方案..
    一个是用 enum
    一个是用 class Action {
    static INCREMENT='increment',
    static DECREMENT = 'decrement'
    };
    yesvods
        6
    yesvods  
    OP
       2016-01-06 16:29:40 +08:00
    @zhuangzhuang1988 无论怎么选择,都需要有一个单例模式的实例引入。而自己定义这些“单例”,必然需要维护额外的 constant 文件。 react-constant 原生就具备单例机制,而且具备命名空间,对 constant 使用简化了不少。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2703 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 12:15 · PVG 20:15 · LAX 04:15 · JFK 07:15
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.