zoukankan      html  css  js  c++  java
  • 《谁都能听懂的 Redux+Redux-Saga 超级傻瓜教程》

    谁都能听懂的 Redux+Redux-Saga 超级傻瓜教程

     

    对不起本文确实有标题党的嫌疑:) 想要理解本文还是要先会用 react 和 es6,如果连 react 和 es6 都不知道是什么的话我也没辙:(

    如果你选择用 react 来开发应用,并且你没对各个组件的状态进行应有的管理,那么当应用变得庞大的时候你会发现组件之间的通信变得错综复杂,各个组件之间的数据传递往往会乱成一团,从而导致加班、延期、炒鱿鱼等不好的事情:( 这个时候就需要引入 “状态管理” 这个概念来挽救一团乱麻的代码。状态管理,就是将各个组件之间相互独立的状态和数据给统一的管控起来,让原本错综复杂的数据流向变成单向,这样状态就变得容易管理和理解,从而让程序变得易于维护。

    今天我们讲的就是 react 目前最流行的状态管理工具 redux 和它的一些周边组件。废话不多说,我们先准备好 react 开发环境,打开 ide 开始敲代码。

    环境这块我就不讲了,最基础的 webpack+react 即可。

    首先先安装 redux(yarn add redux -S),清空 src 目录,新建一个入口 js 文件(index.js),输入以下内容:

    import { createStore } from 'redux'
    
    const reducer = function (state, action) {
      console.log(action.type)
      return state
    }
    
    const store = createStore(reducer)
    
    store.dispatch({type: 'hello'})

    然后启动 dev server,打开浏览器和控制台,就可以看到输出了 “hello”。现在来稍微解释下这段代码:

    createStore,从字面上理解,就是创建仓储,这个仓储用来存放数据和修改数据的方法。

    dispatch,直译过来是指派、调度,可以理解成命令 store 执行修改数据的操作。传入一个对象来描述要执行的动作。我们称这个对象为 action。

    reducer,直译过来是还原剂,这里就把它理解成存放数据和修改数据的方法的地方。如果把 store 比喻成仓库,那么 reducer 就是用来装载货物的集装箱。reducer 接受的第一个参数是数据,第二个参数用来描述动作,里面是 dispatch 过来的对象和数据,我们可以利用 type 属性结合 switch case 语句来进行具体的状态修改。还有要记得返回 state,如果没有返回 state 就会报错。

    我们把 reducer 扔到 createStore 这个函数里,就返回了一个 store。然后再调一下 store 里面的 dispatch 方法,就执行了一次 reducer。这样一个最简单的 redux 管理状态的流程就跑完了。

    在这个例子里我们只使用了一个 reducer,而一个 reducer 只有一个 state,但是我们的应用肯定不止一个组件,这个时候就需要多个 reducer。

    为了将多个 reducer 组合起来,我们又要引入一个 redux 里的函数,叫 combineReducers。

    import {combineReducers, createStore} from 'redux'
    
    const list = function (state = [], action) {  //state=[]表示的是state的初始状态
      console.log(action.type)
      console.log('list')
      return state
    }
    
    const counter = function (state = 0, action) {
      console.log(action.type)
      console.log('counter')
      return state
    }
    
    const reducers = combineReducers({
      list, counter
    })
    
    const store = createStore(reducers)
    
    store.dispatch({type: 'hello'})

    这样就将多个 reducer 组合起来了。调用 dispatch 的时候所有 reducer 都会被执行。

    到了这里我们就已经可以进行一些简单的本地状态管理了。但是几乎所有的应用都有涉及到 ajax 异步请求,这些代码要放到哪里呢?如果放到 reducer 里的话由于 reducer 要求立即返回 state,不然报错。解决方案是有的,不过有些繁琐,可以参考阮一峰老师的教程:

    http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html

    如果没看懂的话也没关系,如果你能够在项目中运用 redux-saga 的话,就可以很轻松的解决异步问题了:)

    我们先认真的把 redux-saga 官方提供的案例给看一看

    https://redux-saga-in-chinese.js.org/docs/introduction/BeginnerTutorial.html

    redux-saga 的使用很简单,和之前 redux 的做法差不多。先定义 saga(也称为 effect。类似 reducer,不过可以调用异步方法,不能修改状态),然后在顶层(index.js)注册之前写好的 saga 即可。

    在 saga(effect)中,我们可以通过 takeEvery 来监听 dispatch,通过 call 来调用异步方法,通过 put 来触发 reducer,通过 select 来获取状态。要注意的是 saga 都是 Generator 函数(带 * 号),也只有 Generator 函数里才能调用 yield。这样异步问题就差不多解决了。

    说了这么多,总得应用到 react 里面去吧。react 里的各个组件想要获取到 store 里的状态和命令 store 进行数据修改,如果不安装其他包的话就只能在根级组件把 store 一级一级的传递下去,中间有一级没传递 store 那么之后的组件就全部无法使用 redux 进行状态管理了,这样显然是有待改进的。所以我们还要再装一个包:react-redux。

    React-redux 核心的方法只有两个:Provider 和 connect。Provider 用来包裹根级组件,并接收 store,connect 用来将组件的 props 与 store 连接起来,这样即使不一层层的传递 store 每个组件也可以接收到 store。

    export default connect((state) => {
      return {list: state.userList.list} // 将store与组件连接起来。connect第一个参数是一个函数,要求返回用来描述props和store的对象。
    })(List)

    这样我们基本上就能把 redux 给实际的应用起来了,但是还有一个问题值得我们思考:store 调用 dispatch 后所有的 reducer 都会被执行,而每个 reducer 里面只能用 switch case 之类的流程控制语句来指定执行哪个 reducer,如果项目一大,各个方法的命名岂不是很容易混乱?别着急,这个时候需要本文要谈到的最后一个包:dvajs。dvajs 将一组数据和相应的修改数据的方法包装成一个 module,组件调用 dispatch 的时候可以通过指定 type 属性来直接调用相应 module 的 effect 或者 reducer。dvajs 的具体使用除了参考官网的案例以外,还可以参照这篇博文:https://www.cnblogs.com/axel10/p/8503782.html。只要你能够从 redux->redux-saga->react-redux 这个流程学下来,就会发现 dvajs 几乎没有多少新知识点,很快就能够上手。

    如果觉得教程里有地方讲的不是很理解的可以将下面这个案例下载下来看一看,相信很多问题都会得到答案。

    一个在线获取用户列表,点击项目可删除的例子

    https://github.com/axel10/react-redux-redux-saga-example

  • 相关阅读:
    C#大小写字母转换函数
    vss安装及服务器端、客户端配置图文教程
    JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)
    LoadRunner 录制IE 8卡死
    LoadRunner 11 安装及破解
    C#开发中常用加密解密方法解析
    Oracle 11g安装图文攻略
    IIS添加域名
    SQL2008中Merge的用法
    在T-SQL语句中访问远程数据库(openrowset/opendatasource/openquery)
  • 原文地址:https://www.cnblogs.com/cx2016/p/13232739.html
Copyright © 2011-2022 走看看