redux概念、基础

1 篇文章 0 订阅

[ demo(基于react) 提取码:b36i ]
demo网盘地址

参考文档:
http://cn.redux.js.org/

1、核心概念

  • state 数据
  • action 是一个普通的js对象,像是描述发生了什么事的指示器,可以知道应用中发生了什么
  • reducer 为了把action和state串起来的而写的函数,只是一个接收state、action,并返回新的state的函数

2、三大原则

(1)单一数据源

  • 整个应用的state被存在一个object tree中,并且这个object tree 只存在唯一的一个store
  • 这个优势可以用来处理:撤销,重做等复杂的功能

(2)state是只读的

  • 唯一改变state的方法就是触发action
  • action是一个用于描述已发生事件的普通对象
  • action可被日志打印、序列化、存储、后期调试、或测试的时候回放出来

(3)使用纯函数来执行修改

  • 为了描述 action 如何改变 state tree ,你需要编写 reducers
  • Reducer 只是一些纯函数,它接收先前的 state 和 action,并返回新的 state
  • 控制它们被调用的顺序,传入附加数据,甚至编写可复用的 reducer

3、Action

(1)定义及注意点

  • 是把数据从应用传到store的有效载荷
  • 是store数据的唯一来源,通过store.dispatch() 将action传到store
  • Action 本质是js 普通对象,约定action 内必须使用字符串类型的 type 字段来表示将要执行的动作
  • 应该尽量减少在 action 中传递的数据,可使用index作为唯一标识,比传递整个对象要好

(2)写法
添加新 todo 任务的 action 是这样的:

const ADD_TODO = 'ADD_TODO'
{
  type: ADD_TODO,
  text: 'Build my first Redux app'
}

当应用规模越来越大时,建议使用单独的模块或文件来存放 action。

import { ADD_TODO, REMOVE_TODO } from '../actionTypes'

4、Action创建函数

(1)定义

  • action创建函数,就是生成action的函数
  • redux中的action创建函数,只是返回一个action

(2)写法

function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}

(3)使用
redux中只需要把action创建函数的结果传给dispatch方法即可,发起一次dispatch过程

dispatch(addTodo(text))
dispatch(completeTodo(index))

或者创建一个 被绑定的 action 创建函数 来自动 dispatch:

const boundAddTodo = text => dispatch(addTodo(text))
const boundCompleteTodo = index => dispatch(completeTodo(index))
// 然后直接调用它们:
boundAddTodo(text);
boundCompleteTodo(index);

store 里能直接通过 store.dispatch() 调用 dispatch() 方法,
但是多数情况下你会使用 react-redux 提供的 connect() 帮助器来调用。
bindActionCreators() 可以自动把多个 action 创建函数 绑定到 dispatch() 方法上。

5、Reducer

(1)定义

  • reducer指定应用状态的变化如何响应action并发送到store
  • action只是描述了有事情发生这一事实,并没有描述应用如何更新state

(2)设计state结构

  • 尽可能地把 state 范式化,不存在嵌套
  • 所有数据放到一个对象里,每个数据以 ID 为主键,不同实体或列表间通过 ID 相互引用数据

(3)action处理

  • reducer 就是一个纯函数,接收旧的 state 和 action,返回新的 state。
;(previousState, action) => newState
  • 重点
    谨记 reducer 一定要保持纯净。
    只要传入参数相同,返回计算得到的下一个 state 就一定相同。
    没有特殊情况、没有副作用,没有 API 请求、没有变量修改,单纯执行计算。

reducer 中不能做的:
修改传入参数;
执行有副作用的操作,如 API 请求和路由跳转;
调用非纯函数,如 Date.now() 或 Math.random()。

写法:当state没有初始值时,可以赋值(es6的默认参数写法)

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    default:
      return state
  }
}

注意:

  • 不要修改 state。 使用 Object.assign() 新建了一个副本。
  • 在 default 情况下返回旧的 state。遇到未知的 action 时,一定要返回旧的 state。

处理多个action处理:引入action、扩展reducer、拆分写法(代码参考reducers文件夹)

  • 每个 reducer 只负责管理全局 state 中它负责的一部分。
  • 每个 reducer 的 state 参数都不同,分别对应它管理的那部分 state 数据。

6、store

(1)定义
Store 就是把 ‘ 使用 reducers 来根据 action 更新 state ’’ 联系到一起的对象。
Store 职责:

  • 维持应用的 state;
  • 提供 getState() 方法获取 state;
  • 提供 dispatch(action) 方法更新 state;
  • 通过 subscribe(listener) 注册监听器;
  • 通过 subscribe(listener) 返回的函数注销监听器。
  • 再次强调一下 Redux 应用只有一个单一的 store。

(2)根据已有的 reducer 来创建 store

import { createStore } from 'redux'
import todoApp from './reducers'
let store = createStore(todoApp)

createStore() 的第二个参数是可选的, 用于设置 state 初始状态。

let store = createStore(todoApp, window.STATE_FROM_SERVER)

(3)发起action

这段代码用于测试数据处理逻辑

import {
  addTodo,
  toggleTodo,
  setVisibilityFilter,
  VisibilityFilters
} from './actions'

// 打印初始状态
console.log(store.getState())

// 每次 state 更新时,打印日志
// 注意 subscribe() 返回一个函数用来注销监听器
const unsubscribe = store.subscribe(() => console.log(store.getState()))

// 发起一系列 action
store.dispatch(addTodo('Learn about actions'))
store.dispatch(addTodo('Learn about reducers'))
store.dispatch(addTodo('Learn about store'))
store.dispatch(toggleTodo(0))
store.dispatch(toggleTodo(1))
store.dispatch(setVisibilityFilter(VisibilityFilters.SHOW_COMPLETED))

// 停止监听 state 更新
unsubscribe()

7、数据流

严格的单向数据流是 Redux 架构的设计核心。

Redux 应用中数据的生命周期(4个步骤)

  • 1、调用 store.dispatch(action)
    action 理解成新闻的摘要。可以在任何地方调用 store.dispatch(action),包括组件中、XHR 回调中、甚至定时器中。
 { type: 'LIKE_ARTICLE', articleId: 42 }
 { type: 'FETCH_USER_SUCCESS', response: { id: 3, name: 'Mary' } }
 { type: 'ADD_TODO', text: 'Read the Redux docs.' }
  • 2、Redux store 调用传入的 reducer 函数。
    Store 会把两个参数传入 reducer: 当前的 state 树和 action。例如,在这个 todo 应用中,根 reducer 可能接收这样的数据:
// 当前应用的 state(todos 列表和选中的过滤器)
let previousState = {
  visibleTodoFilter: 'SHOW_ALL',
  todos: [
    {
      text: 'Read the docs.',
      complete: false
    }
  ]
}

// 将要执行的 action(添加一个 todo)
let action = {
  type: 'ADD_TODO',
  text: 'Understand the flow.'
}

// reducer 返回处理后的应用状态
let nextState = todoApp(previousState, action)
  • 3、根 reducer 应该把多个子 reducer 输出合并成一个单一的 state 树。
    根 reducer 的结构完全由你决定。Redux 原生提供combineReducers()辅助函数,来把根 reducer 拆分成多个函数,用于分别处理 state 树的一个分支。

下面演示 combineReducers() 如何使用。假如你有两个 reducer:一个是 todo 列表,另一个是当前选择的过滤器设置:

function todos(state = [], action) {
  // 省略处理逻辑...
  return nextState
}

function visibleTodoFilter(state = 'SHOW_ALL', action) {
  // 省略处理逻辑...
  return nextState
}

let todoApp = combineReducers({
  todos,
  visibleTodoFilter
})

当你触发 action 后,combineReducers 返回的 todoApp 会负责调用两个 reducer:

let nextTodos = todos(state.todos, action)
let nextVisibleTodoFilter = visibleTodoFilter(state.visibleTodoFilter, action)

然后会把两个结果集合并成一个 state 树:

return {
  todos: nextTodos,
  visibleTodoFilter: nextVisibleTodoFilter
}

虽然 combineReducers() 是一个很方便的辅助工具,你也可以选择不用;你可以自行实现自己的根 reducer!

  • 4、Redux store 保存了根 reducer 返回的完整 state 树。
    这个新的树就是应用的下一个 state!所有订阅 store.subscribe(listener) 的监听器都将被调用;监听器里可以调用 store.getState() 获得当前 state。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值