浅浅谈Redux

logo-title-dark.png

if 读完了 then 你能了解到:

  • 好钢用在刀刃 - redux的应用场景
  • 万变不离其宗 - redux的基本思路

一些唠叨

最近有个任务,就是需要在一个开源项目上进行扩展开发,而这个开源项目用到的是非常主流的 react 和 react-redux,近些年一直在跟 vue 打交道(广告植入:比如开源了一个 vue 版本的 ncform 项目),冷落了 react 有一段时间了,刚好趁机重温下 react 及其周边相关的技术生态

react-redux,其实就是 redux 的 react 版本,方便 redux 在 react 中使用。

而 redux,是 javaScript 应用状态管理容器,是参考 flux 设计模式的一种实现(vue 的 vuex 也是类似的实现),它独立于各种 web 框架但又可融入于各种 web 框架。


哪里才是 redux 用武之地

很多人会认为,引入 redux 会增加应用的复杂性。确实不简单,但存在即合理,所以什么场景下适合使用 redux 就很关键了。

我就开发一个活动页。奉劝你不要用 redux 啦,一点好处都没有,只会增加复杂性。

切记:不要为了用而用 - 然而现实中这种现象是大量存在的

当一个应用的功能越来越多时,开始进行功能模块拆分,这个时候,就会遇到一个问题,功能模块之间共享的数据如何处理,比如登录用户的信息。

例子能再具体点吗?好吧,但还是登录用户信息,哈哈。

比如你在用户模块修改了头像,然后顶栏上的登录头像要实时跟着更新,这个时候,其实是用户模块和顶栏共享了你的用户头像信息

解决这种可能有N种方法,今天既然聊 redux,那就专心讲它吧

当你把数据梳理一下,你会发现有些数据是在模块内共享的,有些数据是在模块间共享的,我们将在模块间共享的称之为应用级别的数据,即 Application 级别,redux 就是专门处理这种级别数据的解决方案


redux 的基本思路

我们用 redux 官方的 todo app 例子来讲解( Warning: 仅为了说得简单,讲得明白,这种小应用是不适合引入 redux 的 )

你的应用有着一份描述着状态(state)的数据,可能如下:

🔸 术语
State: 应用级别的状态数据

{
  todos: [{
    text: 'Eat food',
    completed: true
  }, {
    text: 'Exercise',
    completed: false
  }],
  visibilityFilter: 'SHOW_COMPLETED'
}

这份 state 是静态的,你可以理解为就是应用最初的状态。

当我完成了 Exercise 项,我就打个勾,表示我完成了。此时就需要更改下应用的状态,需要把 Exercise 那一项 的completed 由 false 改成 true。

怎么更改呢?直接把值改了不就完事了?

如果直接改变 state 对象的属性值,就断了 state 更改的轨迹,简单讲就是你修改了一个对象的属性值,你就很难追踪属性值更改前是什么样子了。这在调试排查问题的时候非常有用。

一定有更好的方法,可参考下事件的机制。所以当想更改状态时,我们派发(dispath)一个操作(action),描述清楚我们想干什么,而不是直接就干了。一个操作的描述可能如下:

{ type: 'ADD_TODO', text: 'Go to swimming pool' }
{ type: 'TOGGLE_TODO', index: 1 }
{ type: 'SET_VISIBILITY_FILTER', filter: 'SHOW_ALL' }

🔸 术语
dispatch: 通过该方法主动派发操作
action: 描述操作的内容,type 值必须提供,指定行为的类型,相当于事件的名称

用派发操作的好处:
将每个更改描述为一个操作,让我们清楚地了解应用程序中发生的情况。 如果发生了变化,我们就知道它为什么会改变,操作就像面包屑,使得应用状态的变化有迹可循

OK,至此啥事还没做,只是嘴上嚷嚷我要做什么,那总得有实际处理的方法吧。

没错,这些实际修改状态的方法称为 reducer。实现可能如下:

function visibilityFilter(state = 'SHOW_ALL', action) {
  if (action.type === 'SET_VISIBILITY_FILTER') {
    return action.filter
  } else {
    return state
  }
}
function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return state.concat([{ text: action.text, completed: false }])
    default:
      return state
  }
}

🔸 术语
reducer:它负责接收当前 state 和 action,然后按照 action 的 type,根据当前 state 进行操作,最终返回一个全新的 state(返回全新的 state 保证了 数据修改的可追溯性)。

你会发现 visibilityFilter 返回的是查询条件字符串,而 todos 返回的是列表项数组列表。把它们返回的数据合并起来,就是一个完整的应用状态,如下:

function todoApp(state = {}, action) {
  return {
    todos: todos(state.todos, action),
    visibilityFilter: visibilityFilter(state.visibilityFilter, action)
  }
}

OK,到此为此,想干什么也说了,实际做事的也讲了,但好像还是云里雾里,脑袋里依然没有很清晰的全局的画面,好像还少了什么东西。

告诉你,少了一个管家,它管着应用的状态,它就是 store。

🔸 术语
Store: 管理应用状态数据,负责把 action, reducer 等串起来

我们借用 redux 的一些 api 来完整描述一个数据修改的全过程

  1. 创建 store。通过 reducer 作为参数,store 就可以通过 reducer 获取到应用状态的数据结构
let store = createStore(todoApp)
  1. 监听变化。你可以在应用状态发生变化时做一些事,比如更新DOM
function listener() { console.log(store.getState()) }
store.subscribe(listener)
  1. 派发操作。因为 store 拥有 reducer,所以只要把 action 交给 reducer 处理即可。处理后可以通知执行第2步中订阅的一些操作
let action = { type: 'ADD_TODO', text: 'Go to swimming pool' }
store.dispatch(action)

😫修改了好多次,终于写完了。。。


写在最后

接下来的内容跟本文一毛钱关系都没,只是一如既往地打一波广告:

ncform,一种令人愉悦的表单开发方式,仅需配置即可生成表单UI及其交互行为。
自带丰富的 标准组件 和 校验规则,开箱即用。
具备强大的 控件交互 和 扩展能力,做你所想。
github: https://github.com/ncform/ncform

注:目前只有 vue 版本,希望在不久的将来,有时间发布 react 版本

tags: react, flux, react-redux, redux

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容