三大原则

Rule1

将整个app的state保存在一处,且只有一个state对象

Rule2

dispatch是app里唯一能改变state的方法

Rule3

尽量使用纯函数(比如Reducer),保持数据不变性。

纯函数的特征

  • 不改变传入数据
  • 传入同样的数据,一定会得到同样的结果

通俗来说,就是函数内仅专注于处理传入的数据,在不改变数据的前提下,返回新值。

使用纯函数的一个好处是可以提高性能,举个例子,当我改变一个state,通过新旧state对象进行混合,( 记得Object.assign()吗?),返回新的对象,在新的对象内部我们保持了对Previous state的(or部分)引用,节约了资源,提高一定的性能。Imutable.js 是践行数据不可变性的库,使用它结合react开发,将会大大提升app的性能。

Reducer

顾名思义,它的功能会类似于原生JS里的reduce。它的作用是,接收previous state 和 dispatching action,返回一个新的state. 在后面的具体例子里我们会对reducer这个称呼更有体会。

Action

Action的本质是一个附带了一个叫key为type的对象,它可以仅仅含有这个key和其对应名字(string),因为也许这样就已经足够描述这个action。更加复杂一点的情况下,可能需要附带一些数据(常见于异步请求服务器数据),通常我们使用payload作为key. 常见情况是进行服务器请求返回了数据,我们需要使用这些数据进行状态更新以进行re-render.

常见惯例: 如果reducer接受的previous state是undefined,必须返回一个初始state,这个state是多少需要我们考虑清楚。

Store

它将是我们的RULE1的state保存地点,我们使用createState来创建它,会接收一个reducer函数,返回的将是一个对象,它具有三个函数: getState ,dispatch ,subscribe . 不难想象,在createState的内部应该具有一个state变量,这里应用了闭包使其可以长期保存并更新, 那么,它大概会长成这个样子:

const createStore = (reducer) => {
  let state, // Where we store the state of whole application  
      listeners = [] // Store all subscribed callback function

  const getState = () => {
    // @TODO
  }

  const dispatch = () => {
    // @TODO
  }

  const subscribe = () => {
    // @TODO
  }

  // @TODO

  return { getState, dispatch, subscribe }
}

在使用框架的时候,仅仅搬运API的后果是当一旦应用规模&复杂度提升以后,我们很容易迷失,陷入困惑。为了更好理解它的内部运行机制,我们尝试去粗略的实现它,谨记,我们并不是完全实现真正的API,我们只是对其大概的主要功能进行模拟。

getState

顾名思义,这是一个用来返回当前state 的函数,实现起来很简单。

const getState = () => state

有了这个函数,将这个方法传入组件里再进行调用,通过返回的state来决定渲染内容。

dispatch

核心方法,这是使用redux体系下唯一用来改变state的方法,类似于react里的setState. 在这个方法里,我们要做两件事:

  1. 接收一个action,调用store传入的reducer进行状态更新
  2. 遍历Listener数组,依次调用listener (别急,下面就会解释)
const disptach = action => {
    state = reducer(state, action)
    listeners.forEach(l => l())
}

subscribe

传入一个回调函数,将回调函数注册进一个数组,即上面代码里的listeners ,让store里的state更新后调用它。并返回一个函数,调用这个函数可以让传入的对应回调函数从Listeners 里移除,取消订阅。

const subscribe = listener => {
  listeners.push(listener)
  return () => {
    listeners = listeners.filter(l => l !== listener)
  }
}

函数整体

const createStore = (reducer) => {
  let state, // Where we store the state of whole application  
      listeners = [] // Store all subscribed callback function

  const getState = () => state

  const disptach = action => {
      state = reducer(state, action)
      listeners.forEach(l => l())
  }

  const subscribe = listener => {
    listeners.push(listener)
    return () => {
      listeners = listeners.filter(l => l !== listener)
    }
  }

  dispatch({}) // Just to get the reducer to return the initial value.  
  return { getState, dispatch, subscribe }
}

好,完工! 请回顾一下上面的每个函数内部做了什么,请务必记住,在后面的例子拓展中,随着例子的复杂度提高,这些概念将为我们提供清晰的思路。


下一节我们来看一个例子

results matching ""

    No results matching ""