还在纠结 Flux 或 Relay,或许 Redux 更适合你
重磅消息,Redux 1.0 发布,终于可以放心用于生产环境了!
在这个端应用技术膨胀的时代,每天都有一大堆框架冒出,号称解决了 XYZ 等一系列牛 X 的问题,然后过一段时间就不被提起了。但开发的应用还是需要维护的!所以选择框架时不要只顾着自己用着爽,还要想着以后别人接手时的难易度。
因为 Flux 本身约定不够细致,如何做异步、如何做同构这些非常普遍的问题,官方都没有给出详细的说明。还有 store,view 里一大堆重复代码,极速膨胀的 action 等问题。这也难免会冒出一堆“改良”性的轮子。有一些非常闪光,如 Redux,Reflux,Marty。Reflux 和 Marty 基本上只是去掉重复代码并为现有 Store,Action 增加一些灵活性,用起来比原生 Flux 上手更容易,但是总体二者没有跳出 Flux 的思想,大量依旧采用“传统”的 mixin 方式实现。如果项目不是很复杂可以试试。至于 Relay,由于需要后端 GraphQL 支持,对于采用 REST 接口开发的遗留项目和前后端分离的大团队来说成本切换有点高。
现在开始说今天的主角 Redux。Redux 由 Flux 演变而来,后来受 Elm 启发,去掉了 Flux 的复杂性,到现在越来越自成一派,甚至已经有了 Angular 的实现。最近开始把团队旧的纯 Flux 开发项目逐步往 Redux 上迁移。Redux 还是秉承了 Flux 单向数据流、Store is the single source of truth 的思想,这两点略过。下面谈一下使用 Redux 过程中的其它感受。
特性和优点
文档清晰,编码统一
Redux 文档非常清晰细致,这一点有助于统一团队编码风格,节省了很多纠结和踩坑的时间。再也不纠结 Ajax 请求到底放哪里了,全部丢到 action(通用的也可以放到 middleware) 里就没错。究竟使用 state 还是 props?组件里全部使用 props,只在顶层组件里使用 state。之前为了灵活或兼容性,Redux 的 provider 提供 Provider
decorator 装饰器 和 provider
两种调用用法,现在只建议使用 Provider
decorator。Redux 这点设计思想和 Python 的非常像:
There should be one, and preferably only one - obvious way to do it.
你会发现用了 Redux 后,整个团队写的代码风格都比较一致,上一次有这种感受是项目由旧的 jQuery 组件迁到 React 的时候。如果有些场景你还是纠结怎么办?去 Redux issues 提个 issue 吧,很快就会有人回复。
State, State, State -> Store
前端复杂性在于 view,view 复杂性在于 state 处理。state 复杂是因为包括了 AJAX 返回的数据、当前显示的是哪个 tab 等这些 UI state、表单状态、甚至还有当前的 url 等。Redux 把这些所有的 state 汇总成一个大的对象,起了个名字叫 Store
,没错,就是 Flux 里的 Store
。只是 Redux 限定一个应用只能有一个Store
。单一 Store
带来的好处是,所有数据结果集中化,操作时的便利,只要把它传给最外层组件,那么内层组件就不需要维持 state,全部经父级由 props 往下传即可。子组件变得异常简单。
Reducer
只有一个 Store
,第一感觉是这个 Store
对象会不会非常大?其实对象大并不可怕,可怕的是对象处理逻辑放到一起。只要把这些处理逻辑按处理内容拆分不就可以了吗?!拆分后的每块处理逻辑就是一个Reducer
。把这些 Reducer
里的每块内容合到一起(用 ES6 的 import 语法)就组成了完整的Store
。Reducer
只是一个纯函数,所以很容易测试。提到 Reducer
不得不提函数式编程,reducer 本质就是做对象格式转换,这点用函数式操作实在太高效了。
(previousState, action) => newState
因为是纯函数,组合多个 reducer 非常简单,参见https://gist.github.com/gaearon/d77ca812015c0356654f。顺便也移除了 Flux 里最让人诟病的 waitFor
语法。
Action
Redux 的 action 与 Flux 中的类似,都是表达 view 要改变 store 内容的载体。Flux 是通过统一的Dispatcher
分发 action,Redux 去除了这个 Dispatcher
,使用 store 的 store.dispatch()
方法来把 action 传给 store。由于所有的 action 处理都会经过这个 store.dispatch()
方法,Redux 聪明地利用这一点,实现了与 Koa,Ruby Rack 类似的 Middleware 机制。Middleware 可以让你在 dispatch action 后,到达 store 前这一段拦截并插入代码,可以任意操作 action 和 store。很容易实现灵活的日志打印、错误收集、API 请求、路由等操作。我们团队根据预建立的 action 和请求间的映射直接在这里直接发 Ajax 请求,从此麻麻再也不用担心我异步取数据了。
除了这些之外,还有逆天的 DevTools,可以让应用像录像机一样反复录制和重放。
对于同构应用 Redux 也有很好的支持,这一块团队正在调研,等实际上线后再做分享。
不足或不便
当然使用过程中也有一些不顺利的地方,其实主要还是思想方面的转变。
组件应尽可能无状态化
这也被称为 Smart Component 和 Dumb Component 之间的选择,组件库开发应尽可能做成 Dumb Component。这一点和传统的 jQuery 类普遍使用命令式语法做组件开发有很大不同。如写一个 Dialog,jQuery 组件一般会提供 dialog.show()
, dialog.hide()
方法。但 Redux 要求显示或隐藏应该被当作一个 props,由外部传入来控制。Redux 比 Flux 更严格要求 Store 作为数据来源的惟一性,所以之前能用的组件现在发现直接不能用了。
轮训和 WebSocket 请求的处理
请求的发起要在 action 里做,但是请求的暂停/启动状态要放到 store 里,会增加一些复杂性,但保证了数据的一致性。其实还是未明确 store 是单一数据源的思想。
资料:
官方地址:https://github.com/rackt/redux
中文文档:http://github.com/camsong/redux-in-chinese
项目列表:https://github.com/xgrommx/awesome-redux
同构示例:http://react-redux.herokuapp.com/
对了,听说中文文档翻译的还不错,连 Redux 作者 Dan Abramov 都推了,要不你也看看。
还在纠结 Flux 或 Relay,或许 Redux 更适合你的更多相关文章
- MVC还是MVVM?或许VMVC更适合WinForm客户端
最近开始重构一个稍嫌古老的C/S项目,原先采用的技术栈是『WinForm』+『WCF』+『EF』.相对于现在铺天盖地的B/S架构来说,看上去似乎和Win95一样古老,很多新入行的,可能就没有见过经典的 ...
- Redux/Mobx/Akita/Vuex对比 - 选择更适合低代码场景的状态管理方案
近期准备开发一个数据分析 SDK,定位是作为数据中台向外输出数据分析能力的载体,前端的功能表现类似低代码平台的各种拖拉拽.作为中台能力的载体,SDK 未来很大概率会需要支持多种视图层框架,比如Vue2 ...
- Python中str()与repr()函数的区别——repr() 的输出追求明确性,除了对象内容,还需要展示出对象的数据类型信息,适合开发和调试阶段使用
Python中str()与repr()函数的区别 from:https://www.jianshu.com/p/2a41315ca47e 在 Python 中要将某一类型的变量或者常量转换为字符串对象 ...
- 当你还在纠结于ORM的性能时,我已经远远的把你抛在脑后
最近找工作面试,问到一些过去的工作和项目经验.我把公司用到的ORM框架(LLBL Gen)拿出来谈一谈,说一下他的优势,对方却一直追问ORM的好处,性能方面的问题,让我有时候都不知道如何回答,产生了不 ...
- 还在纠结注册.com域名还是.cn域名?
一.概念 .com域名,国际最广泛流行的通用域名格式.国际化公司都会注册. .com域名:当然也可以选择.net/.org以.com为结尾的国际域名. 例如表示工商企业的 .com. 同时还有 .ne ...
- 还在纠结学什么编程语言吗?Python可能会“教”你做人
这几年为什么Python在中国就火起来了? Python这个东西国,大概是从2017年末开始,突然就火了起来的.此前,对于Python,乃至编程,绝大多数程度上都是专业人士的话题,在普通大众层面上起不 ...
- 阮一峰大神的快排?刚才还在纠结sort()的我!真是个小傻瓜
看到这个标题之后 我毫不犹豫的点进去了 趁现在不忙我赶紧把代码写到了我的小本本上好好研究研究 (写的就不放进来了 有点丑) 研究了下 第一反应 明明能用sort()解决的 为什么非要写这么一大串 但 ...
- 对posintion属性的简单认识,对于还在纠结的同学们,有一定的帮助
position的四个属性值: relative ,absolute ,fixed,static 下面分别讲述这四个属性,以简单代码表示 <div id="parent" ...
- 比Redux更容易上手的状态管理库
前言 当项目越发复杂时,我们发现仅仅是提升状态已经无法适应如此复杂的状态管理了,程序状态变得比较难同步,操作,到处是回调,发布,订阅,这意味着我们需要更好的状态管理方式,于是就引入了状态管理库,如Re ...
随机推荐
- link 与 @import之对比
页面中使用CSS的方式主要有3种:行内添加定义style属性值,页面头部内嵌调用和外面链接调用,其中外面引用有两种:link和@import.外部引用CSS两种方式link和@import的方式分别是 ...
- 不容忽略的——CSS规范
一.CSS分类方法: 公共型样式 特殊型样式 皮肤型样式 并以此顺序引用 <link href="assets/css/global.css" rel="style ...
- android使用shape做selector按钮按下和弹起的动画
平时效果: 按下效果: selector代码: <?xml version="1.0" encoding="utf-8"?> <selec ...
- 设计模式--装饰者设计模式(Decorator)
装饰者模式又叫包装模式. 通过另一个对象来扩展自己的行为,在不破坏类的封装的情况下,实现松耦合,易扩展的效果. 抽象组件角色: 一个抽象接口,是被装饰类和装饰类的父接口可以给这些对象动态地添加职责 ...
- C# Monads的实现(二)
再谈continuation monad 上一篇中我们已经介绍了continuation monad,但是这个monad与Identity,Maybe,IEnumerable monads稍微难于理解 ...
- 1、第一个SpringMVC程序
1.创建如下项目结构 2.在src下的com.springmvc下创建User.java package com.springmvc; public class User { private Stri ...
- Android ListView 无法响应onItemClick事件
当在布局文件中加入了Button.ImageButton.CheckBox.RadioButton等控件(也就是Button或者Checkable的子类控件)的时候,listView是无法响应onIt ...
- HDU 1017 A Mathematical Curiosity(枚举)
题目链接 Problem Description Given two integers n and m, count the number of pairs of integers (a,b) suc ...
- hdu 5876 Sparse Graph icpc大连站网络赛 1009 补图最短路
BFS+链表 代码改自某博客 #include<stdio.h> #include<iostream> #include<algorithm> #include&l ...
- 比较不熟的JavaScript点滴,慢慢前行,附带简单复杂化的php小计算器一份
interface.php <html> <head> <meta charset="utf-8" /> <title>这是一个简单 ...