事情经过是这样的,某个阳光明媚的晚上,跟大多数人一样,在 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
慢着....
好像 comC,comD,comE 都有这个 constant
咳咳,膝盖中箭的有木有,站出来!其实 constant 这个常量在 react 界最先被 flux 框架采用,再后来著名的redux( star 数已经超过 flux ),也采用同样方式定义 action 与 reducer 之间的事件分发机制。引入 constant ,有效解决事件分发时,事件类型的一致性以及清晰逻辑性。
其实一直以来,业界津津乐道的是react 的 vm
,flux/redux 的状态管理机制
,webpack 开发技巧以及插件使用
,react-router 入门
etc.
constant 如此重要的事件结构机制因为可将性太低,往往被大家忽略。其实,细心思考,不难发现,随着项目增大。 constants 目录将会随着数据处理事件迅速膨胀。大家一直维护着这个事件命名机制,身心疲惫有木有。
export KeyMirror({
ADD_TODO: null,
COMPLETE_TODO: null,
SET_VISIBILITY_FILTER: null
})
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-mirror、flux-constants的库都耐不住寂寞了,站出来声张正义。
但是,这些库其中一个致命共同点:
- 我们都依旧需要维护一套 constants
- 不同组件使用的 constants 依旧有可能会因为重复导致不可预知的问题
就一句话:
Fuck off constants.js
我们再也不需要去维护任何的与 constant 有关的文件,也不需要到处去找constants/comA.js
、reducer/comA.js
、action/comA.js
一个个去改命名。
HIDE_ITEM
和 comB 的HIDE_ITEM
可不一样,自家用自家的,互不侵犯。npm install react-constant --save
//ES5 version
var Constant = require('react-constant').Constant;
var constants = Constant('mynamespace');
//ES6 version
import { Constant } from 'react-constant';
let constants = Constant('mynamespace');
<script src="dist/constant.min.js"></script>
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,后续会有更多精彩文章以及开源项目与大家共享,欢迎大家交流讨论。
1
scarlex 2015-11-24 10:09:16 +08:00
支持,占了 react-* 这个坑就好好维护下去
|
2
iwege 2015-11-24 10:20:26 +08:00
你前面加一个模块自己的 namespace 不就好了么?
|
5
zhuangzhuang1988 2015-12-27 23:13:50 +08:00
我想到的是 2 个解决方案..
一个是用 enum 一个是用 class Action { static INCREMENT='increment', static DECREMENT = 'decrement' }; |
6
yesvods OP @zhuangzhuang1988 无论怎么选择,都需要有一个单例模式的实例引入。而自己定义这些“单例”,必然需要维护额外的 constant 文件。 react-constant 原生就具备单例机制,而且具备命名空间,对 constant 使用简化了不少。
|