Redux学习笔记-Vol.2-基础

前端之家收集整理的这篇文章主要介绍了Redux学习笔记-Vol.2-基础前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Prev: Redux学习笔记-Vol.1-介绍

Action

Action是把数据从应用传到store的有效载荷。它是store数据的唯一来源,一般通过store.dispatch()将action传到store。
举个栗子:

  1. const ADD_TODO = 'ADD_TODO';
  2.  
  3. //一个action可以表达为:
  4. {
  5. type: ADD_TODO,text: 'Build my first Redux app'
  6. }

说白了,action就是一个普通的javascript对象,但是有一点要注意:约定这个表示action的对象必须有一个type字段,来表示将要执行的动作。
尽量减少在action中传递数据

Action Creator

Action Creator就是生成action的方法

  1. function addTodo(text){
  2. return {
  3. type: 'ADD_TODO',text
  4. }
  5. }

在Redux中,只需把action creator的结果返回给dispatch()即可发起一次dispatch过程。

  1. dispatch(addTodo(text));

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

  1. const boundAddTodo = (text) => dispatch(addTodo(text));
  2. boundAddTodo();

目前为止,我们写好了一个action.js

  1. //action type
  2. export const ADD_TODO = 'ADD_TODO';
  3. export const TOGGLE_TODO = 'TOGGLE_TODO';
  4. export const SET_VISIBILITY_FILTER = 'SET_VISIBILITY_FILTER';
  5.  
  6.  
  7. //其它常量
  8. export const VisibilityFilters = {
  9. SHOW_ALL: 'SHOW_ALL',SHOW_COMPLETED: 'SHOW_COMPLETED',SHOW_ACTIVE: 'SHOW_ACTIVE'
  10. };
  11.  
  12.  
  13. //action creator
  14. export function addTodo(text){
  15. return {
  16. type: ADD_TODO,text
  17. }
  18. }
  19.  
  20. export function toggleTodo(index){
  21. return {
  22. type: TOGGLE_TODO,index
  23. }
  24. }
  25.  
  26. export function setVisibilityFilter(filter){
  27. return {
  28. type: SET_VISIBILITY_FILTER,filter
  29. }
  30. }

Reducer

有了action以后,现在需要reducer来指明如何更新state。

State结构

要明确的一点是,在Redux应用中,所有的state都被保存在一个单一的对象中。
举个栗子,一个todo应用,需要保存两种不同的数据

  • 当前选中的任务过滤条件

  • 完整的任务列表

  1. {
  2. visiibilityFilter: 'SHOW_ALL',todos: [
  3. {
  4. text: 'Consider using Redux',complete: true
  5. },{
  6. text: 'Keep all state in a single tree',complete: false
  7. }
  8. ]
  9. }

处理action

Reducer是一个函数,接受旧的state和action,返回新的state,形如:

  1. (prevIoUsState,action) => newState

保持reducer纯净非常重要,永远不要在reducer中做这些操作:

  • 修改传入的参数

  • 执行有副作用的操作,如API请求和路由跳转

  • 调用非纯函数,如Date.now()Math.random()

一个纯净的reducer是什么样的呢?
只要传入的参数相同,返回计算得到的下一个state就一定相同。
好,开始写reducer。

  1. import { VisibilityFilters } from './actions';
  2.  
  3. const initialState = {
  4. visibilityFilter: VisibilityFilter.SHOW_ALL,todo: []
  5. };
  6.  
  7. function todoApp(state = initialState,action){
  8. switch (action.type){
  9. case SET_VISIBILITY_FILTER:
  10. return Object.assign({},state,{
  11. visibilityFilter: action.filter
  12. });
  13. default:
  14. return state;
  15. }
  16. }

注意:

  1. 不要修改state。上面的代码中只是使用object.assign()创建了一个副本。

  2. default的情况下,返回旧的state在未知的情况下,一定要返回旧的state!

处理多个action

增加两个ADD_TODOTOGGLE_TODO

  1. case ADD_TODO:
  2. return Object.assign({},{
  3. todos: [
  4. ...state.todos,//ES6大法好
  5. {
  6. text: action.text,complete: false
  7. }
  8. ]
  9. });
  10. case TOGGLE_TODO:
  11. return Object.assign({},{
  12. todos: state.todos.map(function(todo,index){
  13. if (index === action.index){
  14. return Object.assign({},todo,{
  15. completed: !todo.completed;
  16. });
  17. }
  18. return todo;
  19. });
  20. });

拆分reducer

  1. function todos(state = [],action){
  2. switch(action.type){
  3. case ADD_TODO:
  4. return [
  5. ...state,{
  6. text: action.text,completed: false
  7. }
  8. ];
  9. case TOGGLE_TODO:
  10. return state.map(function(todo,index){
  11. if (index === action.index){
  12. return Object.assign({},{
  13. completed: !todo.completed
  14. });
  15. }
  16. return todo;
  17. });
  18. }
  19. }
  20.  
  21. function todoApp(state = initialState,action){
  22. switch(action.type){
  23. case SET_VISIBILITY_FILTER:
  24. return Object.assign({},{
  25. visibilityFilter: action.filter
  26. });
  27. case ADD_TODO:
  28. case TOGGLE_TODO:
  29. return Object.assign({},{
  30. todos: todos(state.todos,action)
  31. });
  32. default:
  33. return state;
  34. }
  35. }

todos依旧接受state,但是这里的state变成了一个数组,todoApp只把需要更新的那一部分state传给todos。这就是reducer合成,是开发Redux应用最基础的模式。
用同样的方法把visibilityFilter拆分出来:

  1. function visibilityFilter(state = SHOW_ALL,action){
  2. switch(action.type){
  3. case SET_VISIBILITY_FILTER:
  4. return action.filter;
  5. default:
  6. return state;
  7. }
  8. }

然和修改总的reducer

  1. function todoApp(state = {},action){
  2. return {
  3. visibilityFilter: visibilityFilter(state.visibilityFilter,action),todos: todos(state.todos,action)
  4. };
  5. }

合并的事,就交给Redux帮你来做:

  1. import { combineReducers } from 'redux';
  2.  
  3. const todoApp = combineReducers({
  4. visibilityFilter,todos
  5. });
  6.  
  7. export default todoApp;

ES6大法好
combineReducers接受的是一个对象,返回一个函数。由此,我们可以把所有的顶级的reducer放到一个独立文件中,通> > 过export暴露出每个reducer函数,然后用import * as reducer引入一个以他们名字作为key的Object:

  1. import { combineReducers } from 'redux';
  2. import * as reducer from './reducers';
  3.  
  4. const todoApp = combineReducers(reducer);
  5. //ES6大法好!

截至目前,我们得到了一个完整的reducers.js

  1. import { combineReducers } from 'redux';
  2. import { ADD_TODO,TOGGLE_TODO,SET_VISIBILITY_FILTER,VisibilityFilters } from './actions';
  3.  
  4. function visibilityFilters(state = SHOW_ALL,action){
  5. switch(action.type){
  6. case SET_VISIBILITY_FILTER:
  7. return action.filter;
  8. default:
  9. return state;
  10. }
  11. }
  12.  
  13. function todos(state = [],{
  14. completed: !todo.completed
  15. });
  16. }
  17. return todo;
  18. });
  19. default:
  20. return state;
  21. }
  22. }
  23.  
  24. const todoApp = combineReducer({
  25. visibilityFilters,todos
  26. });
  27.  
  28. export default todoApp;

Store

在学Store之前,我们先来回顾一下actionreducer

  • Action:用来表示“发生了什么”

  • Reducer:根据“发生了什么”来决定如何更新state

现在需要知道的是,Store的作用就是上述两者联系起来。
关于Store的职责:

  • 维持应用的state

  • getState()方法用来获取state

  • dispatch(action)用来分发action,进而更新state

  • subscribe(listener)注册reducer,并返回一个取消注册函数

FYI:Redux只有一个单一的Store!当逻辑复杂需要拆分的时候,请对Reducer下手,科科。
Now,我们来根据已经写好了的reducer来创建store,so easy~

  1. import { createStore } from 'redux';
  2. import todoApp from './reducers';
  3.  
  4. let store = createStore(todoApp);

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

  1. let store = createStore(todoApp,initialState);

发起actions

现在我们已经有了一个store,来看一下怎么用。

  1. import { addTodo,toggleTodo } from './actions';
  2.  
  3. //获得state
  4. store.getState();
  5.  
  6. //注册订阅),state没触发一次更新,打印之
  7. let unsubscribe = store.subscribe(function(){
  8. console.log(store.getState());
  9. });
  10.  
  11. //发起action
  12. store.dispatch(addTodo('finish your resume.'));
  13. store.dispatch(toggleTodo(0));
  14.  
  15. //停止监听state更新
  16. unsubscribe();

看看这一part做了什么 ↓

  1. //创建了一个store(约定store只有一个!)
  2. import { createStore } from 'redux';
  3. import todoApp from './reducers';
  4.  
  5. let store = createStore(todoApp);

严格的单向数据流(Redux核心)

  1. 发起:store.dispatch(action)

  2. 传递:store将发起的action和当前的state传递给根reducer,根reducer再将这两个参数传递给子reducer们;

  3. 更新:通过了子reducer们的各司其职以后,根reducer把他们的输出合并为一个单一的state树;

  4. 保存:store将这个reducer返回的state保存起来,这一次的数据流结束。

猜你在找的React相关文章