smox 2.0 强势发布!状态管理最佳设计 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
masahiro
V2EX    前端开发

smox 2.0 强势发布!状态管理最佳设计

  •  
  •   masahiro
    132yse 2019-01-07 14:10:33 +08:00 3078 次点击
    这是一个创建于 2474 天前的主题,其中的信息可能已经有所发展或是发生改变。

    唔,大家好呀,我是 132,那个,我又来了::>_<::

    smox 是我去年这个时候写的 react 状态管理库,从最初的 redux 替代品,到 react 版本的 vuex,一直在进步

    直到前阵子,突然来了新的灵感,这次 smox 2.0,不再仅仅是进步品这么简单,内部实现除了还保留发布订阅机制,其他的实现已经不一样了。

    可以这么理解,redux 是 flux、elm 的进步实现,smox 却是 redux 的进步实现

    废话不多说,上 API

    Use

    const state = { count: 2 } const actiOns= { up(state, data) { state.count += data }, down(state, data) { state.count -= data } } const effects = { async upAsync(actions, data) { await new Promise(t => setTimeout(t, 1000)) actions.up(data) } } const store = new Store({ state, actions, effects }) 

    如你所见,actions 和 effects 都是对象,里面存放的是函数,参数为他们要触发的对象

    看似没什么不一样的地方,但是同样的 API 实现,我却冥思了一天

    Nexted

    这里面最重要的是 path 机制,我称之为 nexted-proxy

    actions 和 effects 接受的参数,是被限制作用域的,什么意思?

    const state = { counter:{ count: 2 } } const actiOns= { counter: { up(state, data) { state.count += data }, down(state, data) { state.count -= data } } } @map({ state:['counter/count'], actions:['counter/up','counter/down'] }) 

    也就是说,可以通过包裹对象的形式,进行 store 拆分,smox 会自动将 key 作为 path 不断往下传递,上面的例子中,actions 接收的 state 就是 counter 对象下的 state

    这个机制是 smox 最成功的一个机制了,对比 rematch、dva 的 model 机制更灵活强大,设计上也更精彩√

    Proxy

    immed 是我写的一个小库,可以理解为 immer 的迷你实现

    它的作用和 immer 一样,可以将对象 copy 一份,来保证不可变

    同时,使用 Object.defineproperty 对 IE 进行兼容,我好贴心::>_<::

    架构和 API 设计

    在 smox 中,actions 的方法能够不去 return,是 immed 的功劳,不去 return 会让这个 API 变得好看太多了

    至于 effects,它其实一层副作用的包裹,通常用来异步执行 action

    通过 async/await,也可以不去回调了( then 方法除外),这样以来,这个 API 也变得完美了

    如此,smox 的架构变得非常清晰:

    state <- actions <- effects 形成闭环,完美的架构设计

    以上,再无其他。

    可能你会问,dispatch 去哪儿了? reducer 去哪儿了? action.type 去哪儿了?

    当然是没了。

    redux 设计 dispatch 是为了保证 action 触发的唯一性,也就是 action 必须由 dispatch 触发,最终保证的是 state 只由 action 而改变

    smox 不需要 dispatch 也可以做到,因为 smox 的 actions 是封装过函数,state 最终同样可以保证 state 只通过 action 改变

    所以,对比 redux,smox 的设计中,移除了 dispatch,reducer 这种概念

    同样的作为进步品的 rematch、dva 等,是没有变化的,也就是没有改变 redux 的本质

    smox-react

    看完了 smox,再来看 smox-react

    @map({ state: ['count'], actions: ['up', 'down'], effects: ['upAsync'] }) class Counter extends React.Component { render() { return ( <div> <div>{this.props.count}</div> <div>{this.props.sex}</div> <button OnClick={() => this.props.up(1)}>+</button> <button OnClick={() => this.props.down(1)}>-</button> <button OnClick={() => this.props.upAsync(1)}>异步</button> </div> ) } } 

    如上,最重要的是 map 这个 API,大家可还曾记得 connect ?

    我随便从网上找了个 dva 的 connect 长这样:

    @connect(({ user, login, global = {}, loading }) => ({ currentUser: user.currentUser, collapsed: global.collapsed, fetchingNotices: loading.effects['global/fetchNotices'], notices: global.notices, menuData: login.menuData, redirectData: login.redirectData })) 

    这可能是我……学习 react 见过的最可怕的 API 没有之一了::>_<::

    没有对比就没有伤害,smox 的 map 其实抄自 vuex 的 mapXxx,以字符串数组的形式去遍历,然后筛选出对应的 state 和 函数,注入到组件中

    这个 API 我也封装到极致了可以说::>_<::

    smox-react 还有一处比较讨喜,就是,不再需要 bindActionCreators,毕竟已经不再需要 dispatch 了嘛

    总结

    smox 2.0 是我年前最棒的一次重构了,标题写个最佳应该不过分,至今没有发现能把 API 封装到 smox 这个程度的√

    对比同为进步品的 rematch、dva 等,除了 API 更加好看,还放弃了 redux 原有的机制,是创造,不是封装√

    这一切的一切,仅仅只有 1kb

    最后,放上 smox 的 github 地址:

    https://github.com/132yse/smox

    欢迎试用与 star !

    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5421 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 08:28 PVG 16:28 LAX 01:28 JFK 04:28
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86