滚蛋吧! constant 君

2015-11-24 09:33:15 +08:00
 yesvods

前言

事情经过是这样的,某个阳光明媚的晚上,跟大多数人一样,在 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 之旅:

慢着....
好像 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一个个去改命名。

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

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,后续会有更多精彩文章以及开源项目与大家共享,欢迎大家交流讨论。

2684 次点击
所在节点    React
6 条回复
scarlex
2015-11-24 10:09:16 +08:00
支持,占了 react-* 这个坑就好好维护下去
iwege
2015-11-24 10:20:26 +08:00
你前面加一个模块自己的 namespace 不就好了么?
yesvods
2015-11-24 13:45:22 +08:00
@iwege 有两个问题,一来,会导致模块命名太长,妨碍阅读以及编码。依旧需要自己维护很多个相关的文件,非常麻烦。
yesvods
2015-11-24 13:52:12 +08:00
@scarlex 谢谢,同是广州几乎同龄,倍感亲切啊
zhuangzhuang1988
2015-12-27 23:13:50 +08:00
我想到的是 2 个解决方案..
一个是用 enum
一个是用 class Action {
static INCREMENT='increment',
static DECREMENT = 'decrement'
};
yesvods
2016-01-06 16:29:40 +08:00
@zhuangzhuang1988 无论怎么选择,都需要有一个单例模式的实例引入。而自己定义这些“单例”,必然需要维护额外的 constant 文件。 react-constant 原生就具备单例机制,而且具备命名空间,对 constant 使用简化了不少。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/238414

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX