008_React 状态管理 Redux

Redux 的概念

 Redux 是 JavaScript应用的状态容器,提供可预测化的状态管理;

  • Javascript应用:是指任何Javascript构建的项目,而不是仅仅是React框架构建的项目,当然他们搭配用起来更加顺手;
  • 状态容器:react项目中的state抽离出来集中在对象树状结构中store(状态容器),一个项目只能有一个store(状态容器);
  • 可预测性:对于状态的更新变化都是通过纯函数进行操作的,纯函数的核心就是不管传入什么参数,都不会影响改变你传入参数的值;也就是每个新的state都会在旧的state进行产生,而且还不改变旧的state,这就是可预测性;
     

Redux和Vuex的区别和联系

  • Redux,本身就是一个单纯的状态管理者,我们不追溯它的历史,从使用角度来说:它提供一个全局的对象store,store中包含state对象用以包含所有应用数据,并且store提供了一些reducer方法。这些方法可以自定义,使用调用者得以改变state的值。state的值仅为只读,如果需要更改则必须只能通过reducer。
  • React-Redux,简单来说,它提供了一些接口,用于Redux的状态和React的组件展示结合起来,以用于实现状态与视图的一一对应。
  • Vuex,吸收了Redux的思想,并且针对web应用的开发模式和Vue框架做了优化。所以它在实现了全量Redux的思想以外,为了与Vue框架结合,它也具备了类似React-Redux中的与框架结合的功能(尽管具体使用方式可能有差异),此外还一些更好用的特性
     

store和state是最基本的概念,Vuex没有做出改变。其实Vuex对整个框架思想并没有任何改变,只是某些内容变化了名称或者叫法,通过改名,以图在一些细节概念上有所区分。

  • Vuex弱化了dispatch的存在感。Vuex认为状态变更的触发是一次“提交”而已,而调用方式则是框架提供一个提交的commit API接口。
  • Vuex取消了Redux中Action的概念。不同于Redux认为状态变更必须是由一次”行为”触发,Vuex仅仅认为在任何时候触发状态变化只需要进行mutation即可。Redux的Action必须是一个对象,而Vuex认为只要传递必要的参数即可,形式不做要求。
  • Vuex也弱化了Redux中的reducer的概念。reducer在计算机领域语义应该是”规约”,在这里意思应该是根据旧的state和Action的传入参数,”规约”出新的state。在Vuex中,对应的是mutation,即”转变”,只是根据入参对旧state进行”转变”而已。
  • 总的来说,Vuex通过弱化概念,在任何东西都没做实质性削减的基础上,使得整套框架更易于理解了。
  • 另外Vuex支持getter,运行中是带缓存的,算是对提升性能方面做了些优化工作,言外之意也是鼓励大家多使用getter。
     

什么用Redux? 

先谈谈react,react是由facebook公司开源的前端框架;主要用于构建前端界面,将项目中的前端界面进行组件化处理,也就是说react是解决DOM层面上的抽象层;

对于一个完整的前端项目来说,这样是仅仅不够的,它并没有很好的解决组件之间的通信,只通过形式props实现了简单结构的组件通信,对于复杂结构的组件,如果进行采用props形式实现通信,会使整个项目变得难以维护,项目结构混乱(props嵌套传递层次太深);因此诞生出了另一套解决方案:基于Flux架构实现的Redux状态管理框架;

redux运作机制

redux中state属于状态容器,用来存放相应的数据状态,然后在自定义Action规则,它是把数据从应用传到 store 的有效载荷。属于 store 数据的唯一来源。你可以通过 store.dispatch() 将 action 传到 store。执行reducer纯函数进行数据状态更改;其中store是将它们连接起来的概念化的标识;redux具体运行机制如下图所示:

Redux 名词解释

  •  createStore

    创建 store 对象,包含 getState, dispatch, subscribe, replaceReducer

  • reducer

    reducer 是一个计划函数,接收旧的 state 和 action,生成新的 state

  • action

    action 是一个对象,必须包含 type 字段

  • dispatch

    dispatch( action ) 触发 action,生成新的 state

  • subscribe

    实现订阅功能,每次触发 dispatch 的时候,会执行订阅函数

  • combineReducers

    多 reducer 合并成一个 reducer

  • replaceReducer

    替换 reducer 函数

  • middleware

    扩展 dispatch 函数!

你再看 redux 流程图,是不是大彻大悟了?

redux 流程图

 

Redux使用(后面使用react-redux会比较简单易懂)

首先使用 命令行 安装 redux

cnpm install redux --save

然后在 src 目录下 创建一个 store文件夹,创建index.js 文件 作为入口,创建reducer.js 文件(数据管理员)用于存放并暴露 state数据

其中 crateStore ()函数是用于创建 store对象的,将引入的 reducer 作为参数创建一个 store对象并暴露出去即可。

 

获取store的值

在页面中引入store即可通过store.getState()函数获取state的值

 

 

 改变 store 的值

 像Vue改变数据需要通过提交mutation一样,React改变Store的值需要使用action进行提交,通过action对象中的type作为判断操作类型,然后使用dispatch()函数进行action数据和操作类型的提交即可改变 store的值

给input输入框绑定修改的响应函数

<Input placeholder={this.state.inputValue} onChange={this.changeInput.bind(this)}></Input>

 函数体里面通过创建一个action对象,规定使用一个type字段作为描述此次操作的类型,再绑定具体的数据,通过store.dispatch(action)提交修改

  // 输入框改变值的响应函数
  changeInput(e) {
    console.log(e.target.value);
    //  定义 action 对象,type表示此次操作的类型,
    const action = {
      type: "changeInput",
      value: e.target.value
    };
    store.dispatch(action);//提交数据操作
    console.log(store.getState()); // 打印新的数据
  }

 然后在reducer.js  文件中添加对这类型操作数据的方法

查看页面,store的值确实已经改变了

 

 更新store后页面的state也要更新

 

 由上面可以看到,与Vue不同的是,你store的数据即使已经改变,但是页面并没有更新数据,所以此时需要使用订阅函数给你的组件绑定更新,不订阅不会重新设置组件的state。

使用store.subscribe()传入更新函数进行订阅

其中更新函数要做的操作就是将新的store的值获取回来后设置给组件的state

  完成store更新、组件state更新和页面更新

 

push数据

绑定一个新增按钮将输入框的值push到 store的数据列表字段中(记得函数要绑定this)

 

然后在reducer.js 文件中 新增判断类型分支来进行数据操作即可(可用switch简化操作)

所以 一次 对 store数据的操作分为以下几个步骤

  1. 安装redux(--save)
  2. src下创建store文件夹(index.js 文件 作为入口 暴露 store,reducer.js 文件(数据管理员)用于存放并暴露 state数据)
  3. 在页面中引入store即可通过store.getState()函数获取state的值
  4. 绑定响应事件
  5. 在事件里编写Redux的Action
  6. 将Action通过 store.dispatch()函数进行提交
  7. 绑定订阅更新函数(每个组件只需要一次)
  8. reducer业务逻辑的实现

 

文件结构优化

  • actionTypes.js

为了防止 action 拼写错误(没做处理会没有任何反应,难以排查)以及代码冗余(查询操作可能很多地方都要用到)

在 store 文件夹下 创建 actionTypes.js 文件,将用到的 action的类型名称封装成常量,在需要使用的组件还有reducer.js文件中引入这些类型常量即可避免 代码冗余 和异常错误

 

  • actionCreators.js文件

将 action 里的 提交数据操作封装到专门的 actionCreator.js文件作为函数的形式抛出(组件内保留store.dispatch提交数据),在有需要的地方引入函数即可。

 

注意点

  • store必须是唯一的,多个store是坚决不允许,只能有一个store空间(只能在store下的index.js文件中调用一次createStore()函数)
  • 只有store能改变自己的内容,Reducer不能改变(store直接操作数据,reducer只是返回一个操作后的state数据)
  • Reducer必须是纯函数(不能调用Date类或者发请求数据接口的操作),异步请求的数据可以作为参数传递给Reducer处理函数进行初始化
componentDidMount(){
    axios.get('https://www.easy-mock.com/mock/5cfcce489dc7c36bd6da2c99/xiaojiejie/getList').then((res)=>{    
        const data = res.data
        // 将异步请求的数据作为参数传递到reducer.js文件中进行初始化
        const action = getListAction(data)
        store.dispatch(action)
    })
}

 

 

react-redux的使用

React-Redux是一个React生态中常用组件,它可以简化Redux流程。

首先使用reac-redux 需要先安装 redux

cnpm install --save redux react-redux

  同样的,需要在新的项目的src目录下创建store文件夹,以及里面的index.js文件和reducer.js文件

     

 

react-redux 访问store的数据 

 Provider 提供 访问 store的操作

从react-redux中引入Provider,然后引入store,在Provider标签中绑定store字段为引入的store,其子标签里的值都能访问该store

 connect 连接 提供的store

 在组件中引入connect连接父标签Provider提供的store,创建映射对象即可通过this.props.属性 访问store的数据

 

 

 

使用react-redux 修改 store数据

 之前的redux修改数据需要在函数中创建action或者通过actionCreators的函数进行action数据的创建,然后store.dispatch(action)进行提交,现在react-redux的做法如下。

 

 

效果

 

使用react-redux push数据到store

 

  效果

 

Redux DevTools工具使用

第一步 科学上网下载Redux DevTools插件在浏览器上

第二步 按照示例位置输入window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())

import {createStore} from 'redux'
import reducer from './reducer'
// 创建store 并将reducer作为参数传入
const store = createStore(reducer,
// 使用redux—tool工具
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())
export default store

 

总结

react-redux仅有2个API,Provider和connect

1.  Provider是顶层组件的作用,将store作为上下文提供给全局共享。Provider是一个提供器,只要使用了这个组件,组件里边的其它所有组件都可以使用store了,这也是React-redux的核心组件了。Provider 使组件层级中的 connect() 方法都能够获得 Redux store。正常情况下,你的根组件应该嵌套在 <Provider> 中才能使用 connect() 方法

ReactDOM.render(
            <Provider store={store}>
                 <App />
            </Provider>,
            document.getElementById('root')
 )

2. connect方法做的事情是将state和dispatch绑定到Connect组件的参数上,Connect组件是局部组件,将某个react组件包装起来,传递指定的state和props给该组件访问,把UI组件(无状态组件)和业务逻辑代码的分开,然后通过connect再链接到一起,让代码更加清晰和易于维护。

 Redux和Vuex的对比

完全理解 redux(从零实现一个 redux)

Redux入门教程——阮一峰

技术胖 redux教学视频

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值