1、传统MVC框架的缺陷

模型(model)-视图(view)-控制器(controller)的缩写

V即View视图:用户看到并与之交互的界面。

M即Model模型是管理数据:很多业务逻辑都在模型中完成。在MVC的三个部件中,模型拥有最多的处理任务。

C即Controller控制器:接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。

缺点

MVC框架的数据流很理想,请求先到Controller, 由Controller调用Model中的数据交给View进行渲染.

但是在实际的项目中,又是允许Model和View直接通信的。

2、Flux

在2013年,Facebook让React亮相的同时推出了Flux框架,React的初衷实际上是用来替代jQuery的,Flux实际上就可以用来替代Backbone.jsEmber.js等一系列MVC架构的前端JS框架。

其实FluxReact里的应用就类似于Vue中的Vuex的作用,但是在Vue中,Vue是完整的mvvm框架,而Vuex只是一个全局的插件。

React只是一个MVC中的V(视图层),只管页面中的渲染,一旦有数据管理的时候,React本身的能力就不足以支撑复杂组件结构的项目,在传统的MVC中,就需要用到Model和Controller。Facebook对于当时世面上的MVC框架并不满意,于是就有了Flux, 但Flux并不是一个MVC框架,他是一种新的思想

  • View: 视图层
  • ActionCreator(动作创造者):视图层发出的消息(比如mouseClick)
  • Dispatcher(派发器):用来接收Actions、执行回调函数
  • Store(数据层):用来存放应用的状态,一旦发生变动,就提醒Views要更新页面

Flux的流程:

  1. 组件获取到store中保存的数据挂载在自己的状态上
  2. 用户产生了操作,调用actions的方法
  3. actions接收到了用户的操作,进行一系列的逻辑代码、异步操作
  4. 然后actions会创建出对应的action,action带有标识性的属性
  5. actions调用dispatcher的dispatch方法将action传递给dispatcher
  6. dispatcher接收到action并根据标识信息判断之后,调用store的更改数据的方法
  7. store的方法被调用后,更改状态,并触发自己的某一个事件
  8. store更改状态后事件被触发,该事件的处理程序会通知view去获取最新的数据

3、Redux

注意:flux、redux都不是必须和react搭配使用的,因为flux和redux是完整的架构,在学习react的时候,只是将react的组件作为redux中的视图层去使用了。

React 只是 DOM 的一个抽象层,并不是 Web 应用的完整解决方案。

有两个方面,它没涉及:

  • 代码结构
  • 组件之间的通信

2013年 Facebook 提出了 Flux 架构的思想,引发了很多的实现。2015年,Redux 出现,将 Flux 与函数式编程结合一起,很短时间内就成为了最热门的前端架构。

使用场景设计思路

不需要redux情况

  • 用户的使用方式非常简单
  • 用户之间没有协作
  • 不需要与服务器大量交互,也没有使用 WebSocket
  • 视图层(View)只从单一来源获取数据

需要redux情况

  • 用户的使用方式复杂
  • 不同身份的用户有不同的使用方式(比如普通用户和管理员)
  • 多个用户之间可以协作
  • 与服务器大量交互,或者使用了WebSocket
  • View要从多个来源获取数据

从组件层面考虑,什么样子的需要Redux:

  • 某个组件的状态,需要共享
  • 某个状态需要在任何地方都可以拿到
  • 一个组件需要改变全局状态
  • 一个组件需要改变另一个组件的状态

Redux的设计思想:

  1. Web 应用是一个状态机,视图与状态是一一对应的。
  2. 所有的状态,保存在一个对象里面(唯一数据源)。

Redux的使用的三大原则:

  1. store:单一数据源

    整个应用的 state 被储存在一棵对象结构中,并且这个对象结构只存在于唯一一个 store 中

    不能直接去修改此数据源中的数据(数据深拷贝)
  2. State:是只读的

    state redux中的state

    唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。

    action只能是一个对象
  3. reducer:使用纯函数(reducer)来执行修改

    为了描述 action 如何改变 state tree ,你需要编写 reducer,reducer只是一些纯函数,它接收先前的 state 和 action,并返回新的 state

Redux框架的使用



Reducer必须是一个纯函数

纯函数遵守以下一些约束。

  • 不得改写参数
  • 不能调用系统 I/O 的API
  • 不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果

步骤1:创建统一数据源

  1. 引入redux 生成createStore
  2. 创建默认数据 defaultState
  3. 创建 reduces(state,action){}
  4. createStore(reduces)创建数据源
//引入创建仓库方法
import {createStore} from 'redux'
//默认数据源数据,不能直接修改
const defaultStore={
count:1
}
//reducer出函数
function reducers(state=defaultStore,action){
if(action.type=='incr'){
return{
count:state.count+1
}
}
return state
}
//创建唯一仓库
const store = createStore(
reducers,
)
export default store

步骤2:组件中获取数据并设置数据

  1. 获取数据 store.getState()
  2. 订阅数据 store.subscribe(()=>{this.setState(state=>store.getState())})
  3. 派发任务 store.dispatch(actionCreator)
import React,{Component} from 'react'
import store from './store'
export default class App extends Component{
constructor(props){
super(props)
this.state = store.getState()
store.subscribe(()=>{
this.setState(state=>store.getState())
})
}
render(){
return(
<div>
<button onClick={this.incr}>++</button>
</div>
)
}
incr=()=>{
const actionCreator=>{
type:'incr',
payLoad:1
}
store.dispatch(actionCreator)
}
}

划分reducer

原因:一个应用只有一个state,单个reducer对数据操作很臃肿,so需要按照不同功能去拆分

注意:

  1. 分离reducer的时候,每一个reducer维护的状态都应该不同
  2. 通过store.getState获取到的数据也是会按照reducers去划分的
  3. 划分多个reducer的时候,默认状态只能创建在reducer中,因为划分reducer的目的,就是为了让每一个reducer都去独立管理一部分状态

react-redux(redux扩展库)

React-Redux是Redux的官方针对React开发的扩展库。

你可以理解为react-redux就是redux给我们提供一些高阶组件

安装

npm i -S redux react-redux

两个核心的api

  1. Provider: 提供store

    根据单一store原则 ,一般只会出现在整个应用程序的最顶层。
  2. connect: 用于连接容器组件和展示组件

    语法格式为:connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)(component)

    一般来说只会用到前面两个,它的作用是:

    • store.getState() 转化为展示组件的props
    • actionCreators 转化为展示组件props上的方法

使用

步骤1:定义Provider

  • 主程序index.js中定义Provider
  • 让全局的组件共享store中的数据
    import React from 'react'
    import ReactDOM from 'react-dom'
    import { Provider } from 'react-redux'
    import store from './store'
    import App from './App'
    ReactDOM.render(
    <Provider store={store}>
    <App />
    </Provider>,
    document.getElementById('root')
    )

步骤2:子程序中使用connect

  • store.getState() 转化为展示组件的props
  • actionCreators 转化为展示组件props上的方法
  1. 传统使用方式
  2. 装饰器使用方式(推荐使用)

传统使用方式

import React ,{Component} from 'react'
import {connect} from 'react-redux'
import * as actions frm './countAction'
class App exteds Component{
render(){
return (
<div>
{this.props.count}
<button onClick={this.incr}>++</button>
</div>
)
}
incr=()=>{
this.props.incr()
}
}
const mapStateProps=state=>{
return {count:state.count}
}
const mapPropsToDIspatch=dispatch=>{
return{
incr(){
dispatch(actions.incr())
}
}
}
export default connect(mapStateProps,mapPropsToDIspatch)(App)

装饰器使用方式(推荐使用)

import React ,{Component} from 'react'
import {connect} from 'react-redux'
import * as actions frm './countAction'
const mapStateProps=state=>{
return {count:state.count}
}
const mapPropsToDIspatch=dispatch=>{
return{
incr(){
dispatch(actions.incr())
}
}
}
@connect(mapStateProps,mapPropsToDIspatch)
class App exteds Component{
render(){
return (
<div>
{this.props.count}
<button onClick={this.incr}>++</button>
</div>
)
}
incr=()=>{
this.props.incr()
}
}

Redux异步操作(redux-thunk)

通常情况下,action只是一个对象,不能包含异步操作,这导致了很多创建action的逻辑只能写在组件中,代码量较多也不便于复用,同时对该部分代码测试的时候也比较困难.

常见的异步库:

  • Redux-thunk
  • Redux-saga
  • Redux-effects
  • Redux-side-effects
  • Redux-loop
  • Redux-observable

基于Promise的异步库:

  • Redux-promise
  • Redux-promises
  • Redux-simple-promise
  • Redux-promise-middleware

安装

npm i -S redux-thunk

使用

在createStore实例store中使用

import {createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import reducer from './countReducer'
const store = createStore(
reducer,
applyMiddleware(thunk)
)
export default store

countReducer.js

const incrAction = num=>({
type:'incr',
payload:num
})
export const incr=>90=>dispatch=>{
setTimeout(()=>{
let num=10
dispatch(incrAction(num))
},1000)
}

react之redux状态管理的更多相关文章

  1. 微信小程序里使用 Redux 状态管理

    微信小程序里使用 Redux 状态管理 前言 前阵子一直在做小程序开发,采用的是官方给的框架 wepy , 如果还不了解的同学可以去他的官网查阅相关资料学习:不得不说的是,这个框架确相比于传统小程序开 ...

  2. react+redux状态管理实现排序 合并多个reducer文件

    这个demo只有一个reducer 所以合并reducer这个demo用不到 ,但是我写出来这样大家以后可以用到,很好用,管理多个reducer,因为只要用到redux就不会只有一个reducer所以 ...

  3. Redux状态管理方法与实例

    状态管理是目前构建单页应用中不可或缺的一环,也是值得花时间学习的知识点.React官方推荐我们使用Redux来管理我们的React应用,同时也提供了Redux的文档来供我们学习,中文版地址为http: ...

  4. react框架的状态管理

    安装: cnpm install --save redux cnpm install --save react-redux   安装好后导入模块内容: impor {createStore} from ...

  5. React 回忆录(四)React 中的状态管理

    Hi 各位,欢迎来到 React 回忆录!

  6. 对于React各种状态管理器的解读

    首先我们要先知道什么是状态管理器,这玩意是干啥的? 当我们在多个页面中使用到了相同的属性时就可以用到状态管理器,将这些状态存到外部的一个单独的文件中,不管在什么时候想使用都可以很方便的获取. reac ...

  7. 为了弄懂Flutter的状态管理, 我用10种方法改造了counter app

    为了弄懂Flutter的状态管理, 我用10种方法改造了counter app 本文通过改造flutter的counter app, 展示不同的状态管理方法的用法. 可以直接去demo地址看代码: h ...

  8. 借鉴redux,实现一个react状态管理方案

    react状态管理方案有很多,其中最简单的最常用的是redux. redux实现 redux做状态管理,是利用reducer和action实现的state的更新. 如果想要用redux,需要几个步骤 ...

  9. [Full-stack] 状态管理技巧 - Redux

    资源一: In React JS Tutorials, lectures from 9. From: React高级篇(一)从Flux到Redux,react-redux 从Flux到Redux,再到 ...

随机推荐

  1. WebMagic 爬虫技术

    WebMagic WebMagic 介绍 WebMagic基础架构 Webmagic 的结构分为 Downloader.PageProcessor.Scheduler.Pipeline四大组件,并由 ...

  2. MyCat的快速搭建

    1. 概述 老话说的好:一个好汉三个帮,一个人再聪明.再有本事,也要借助他人的力量,才能成功. 言归正传,今天我们来聊聊 MyCat的快速搭建. 2. 场景介绍 服务器A IP:192.168.1.2 ...

  3. MIPS指令 MIPS架构

    华中科技大学 - 计算机组成原理 华中科技大学 - 计算机硬件系统设计 Microprocessor without Interlocked Pipleline Stages 无内部互锁流水级的微处理 ...

  4. Mybatis 一对多延迟加载,并且子查询中与主表字段不对应 (19)

    Mybatis  一对多延迟加载,并且子查询中与主表字段不对应应用说明. 实现一对多关联(懒加载),一个教研组对应多个教师,既:教师的教研编号与教研组的教研编号关联,并且教师关联教研组外键与教研组编号 ...

  5. 【UE4 C++ 基础知识】<9> Interface 接口

    概述 简单的说,接口提供一组公共的方法,不同的对象中继承这些方法后可以有不同的具体实现. 任何使用接口的类都必须实现这些接口. 实现解耦 解决多继承的问题 蓝图使用 使用方法 三种调用方法的区别 调用 ...

  6. JDBC:(java database Connection) java数据库连接。

    JDBC 指 Java 数据库连接,是一种标准Java应用编程接口( JAVA API),用来连接 Java 编程语言和广泛的数据库. JDBC连接步骤: 1.先导入jar包,把jar放入到工程下并 ...

  7. 【Azure 应用服务】App Service For Linux 如何在 Web 应用实例上住抓取网络日志

    问题描述 在App Service For Windows的环境中,我们可以通过ArmClient 工具发送POST请求在Web应用的实例中抓取网络日志,但是在App Service For Linu ...

  8. Java:LinkedHashMap类小记

    Java:LinkedHashMap类小记 对 Java 中的 LinkedHashMap类,做一个微不足道的小小小小记 概述 public class LinkedHashMap<K,V> ...

  9. [敏捷软工团队博客]Beta设计和计划

    项目 内容 2020春季计算机学院软件工程(罗杰 任健) 博客园班级博客 作业要求 Beta设计和计划 我们在这个课程的目标是 在团队合作中锻炼自己 这个作业在哪个具体方面帮助我们实现目标 对Beta ...

  10. 使用cerebro可视化ElasticSearch集群信息

    使用cerebro可视化ElasticSearch集群信息 一.背景 二.安装步骤 1.下载并解压 2.配置cerebro 3.启动 cerebro 4.启动界面 三.注意事项 四.参考文档 一.背景 ...