Redux 独立的集中式状态管理 js 库 - 参见 My Git

不是 react 库,可以与 angular、vue 配合使用,通常和 react 用

yarn add redux

import {createStore} from "redux"

const store = createStore(myCounter);    // 1. 核心 API - 参数是 reducer 函数---> 根据现有的状态及 action 返回一个新的状态,给 store 管理

import {INCREMENT, DECREMENT} from "./action-types"    // 有几个 case,就要定义几个 action 工厂

export default function myCounter(state=0, action){    // 由 store 内部调用,初始值为 0 ./redux/reducers

switch(action.type){    // action 一定要有一个 type 属性

case INCREMENT:{return state+action.numbe;brack;}

case INCREMENT:{return state+action.numbe;brack;}

default: return state

}

}

<App store={store}

import {INCREMENT, DECREMENT} from "./action-types"

export const INCREMENT = "increment";

export const DECREMENT = "decrement";

import * as actions from "../redux/actions";

this.props.store.dispatch(actions.increment(number));    // action creator 产生一个 action 对象,然后 dispatch 这个行为 action

// 虽然等同于 this.props.store.dispatch({type: INCREMENT, number}); 但是一般不这么做

// 工厂函数 - 每次调用,返回一个新的对象 - 每次都返回一个 actions

this.props.store.getState();

  • action

如果是 对象,则是 同步 action ---- 返回一个对象,描述行为、state 参数

export const menuTitle = (menuTitle)=>({tyle: SETMENUTITLE, data: menuTitle})

如果是 函数,则是 异步 action

返回一个 函数,该函数接收一个 dispatch 参数

该函数内部进行异步操作,有了结果以后,再 dispatch 同步 action

export const login = ()=>{

return dispatch=>{

// 1. 执行异步代码

const result = await requestLogin(username, password);

// 2. 分发同步 action

if(result.status === 0){

}else{

}

}

}

  • reducer

根据现有的 state 和 action 生成新的 state

  • const store = createStore(myReducer)    // 根据 n 个现有需要管理的 state 和 action 返回一个新的 state,给 store 集中管理
  • store 最核心的 管理对象---- 与 react 的交互就是 读 和 更新

存储状态数据的对象

维护着 state 和 reducer

核心方法

  • 获取状态 store.getState()   
  • 更新状态 store.dispatch(action-creator) 

对象 action

  • 必须有 type 标识属性,值为字符串
  • 可选数据属性,值为任意类型
  • 订阅一个监听函数 subscribe(listener)

什么时候用 redux?

某个组件的状态需要共享

一个组件需要改变全局状态

一个组件需要改变另一个组件的状态

总体原则: 能不用就不用,如果不用比较吃力才考虑使用

不用 redux 时的集中状态管理?

将多个组件的共用状态放在共同的父组件中

将状态的相关方法定义在与状态相同的组件中

官方实例分析?

redux 编程:

---------------------------------------------------------------------------------------------------------

src/redux/store.js

import {createStore} from "redux"

import reducer from "./reducer"

export default creareStore(reducer);    // 创建 store 对象,内部会第一次自调用 reducer 函数得到一个初始的状态值进行保存

---------------------------------------------------------------------------------------------------------

src/redux/reducer.js

import {INCREMENT, DECREMENT} form "./action-types"

export default  function count(state=1 action){    // 管理 count 就可以叫 count,state 本身就是要管理的数据,第一次展示显示 1

switch(action.type){

case INCREMENT:{return state+action.number;}

case INCREMENT:{return state-action.number;}

default: return state;    // 不做任何处理

}

}

---------------------------------------------------------------------------------------------------------

src/redux/actions.js    // 包含 n 个 action-creator 函数

import {INCREMENT, DECREMENT} form "./action-types"

export const increate = (number)=>({type: INCREMENT, number});

export const decreate = (number)=>({type: DECREMENT, number});

---------------------------------------------------------------------------------------------------------

src/redux/action-types.js    // 多个 js 共用

export const INCREMENT = "increment";

export const DECREMENT = "decrement";

---------------------------------------------------------------------------------------------------------

src/index.js

import React from "react"

import ReactDOM from "react-dom"

import App from "./App.jsx"

import store from "./redux/store"

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

store.subscribe(()=>{

ReactDOM.ummountComponentAtNode(document.getElementById("root"));    // 先卸载原来的组件

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

})

---------------------------------------------------------------------------------------------------------

src/App.jsx

import React, {PureComponent} from "react"

import * as actions from "./redux/actions"

export default class App extends PureComponent{

increment = ()=>{

const number = +this.refs.numberSelect.value;

this.props.store,dispatch(actions.increment(number));

}

decrement = ()=>{

const number = +this.refs.numberSelect.value;

this.props.store,dispatch(actions.decrement(number));

}

render(){

const count = this.props.store.getState();

}

}

问题: react 与 redux 耦合度太强了,直接使用了 store

解决: 使用 react 的插件库 react-redux ---- 简化 react 中使用 redux

----------------------------------------- react 与 redux 的连接--------------------------------------------

Provider

向所有容器组件提供 store

connect(生成 容器组件,负责向 UI 组件传递标签属性

第一参数: 函数 ---- 一般属性从 state 中获取

state=>({title: state.menuTitle})

第二参数: 原始函数/简写对象{actionCreator1, action2}---- 函数属性,执行 dispatch 分发 action-creator

)(UI组件)

---------------------------------------------------------

src/index.js

import React from "react"

import ReactDOM from "react-dom"

import App from "./App.jsx"

import store from "./redux/store"

import {Provider} from "react-redux"

-------------------------------------------------------------------------------------------------------------------

src/App.jsx

import React, {PureComponent} from "react"

import {connect} from 'react-redux'

imoprt Counter from "./components/Counter"

imoprt {increment, decrement]} from "./redux/actions"

function mapStateToProps(state){    // 读取 state 数据,并将其映射成 UI 组件的一般属性

return {count: state}

}

function mapDispatchToProps(dispatch){    // 为 UI 组件映射函数属性,函数内部必须 dispatch,分发 action,产生新的 state,重新 render

return {

incremrnt: number=>dispatch(increment(number))

decremrnt: number=>dispatch(decrement(number))

}

}

export default connect(

mapStateToProps,    // 用来确定向 UI 组件传递哪一些一般属性 count

mapDispatchToProps    // 用来确定向 UI 组件传递哪些函数属性 increment、decrement

)(Counter)        // 用 connect 函数包装一下 App 组件,返回一个新的组件对象

-------------------------------------------------------------------------------------------------------------------

src/components/Counter.jsx

1

react-redux 将组件分为

UI 组件

不会使用任何 redux 相关的语法

最终,值还是要被 store 管理的 ,getState()、dispatch()、

容器组件: 通过 connect 包装 UI 组件生成的组件,内部可以看见 store

1. 向 UI 组件传递一般属性,属性值 会以 state 传递

传递 状态 以及操作 store  的相关函数到 reducer 中

2. 属性值函数内部必然执行 dispatch 去分发 action

最终的简洁写法-------------------------------------------------------------------------------------

redux 异步编程

下载 异步中间件 yarn add redux-thunk

store.js

import thunk from "redux-thunk"    // 中间件,扩展 redux 使其可以 action-creator 可以返回 函数

import {createStore, applyMiddleware} from "redux"

import reducer from "./reducer"

export default createStore(reducer, applyMiddleware(thunk));

actions.js 红中增加 异步 action  

返回的是一个函数,函数会接收一个参数:dispatch

dispatch函数可以执行异步代码, 有了结果,再分发一个同步的 action

export const increment = (number)=>({type:"increment", number})

export const incrementAsync = number=>{

return dispatch=>{

setTimeout(()=>{

dispatch(increment(number))

}, 1000)

}

}

redux 与 chrome 调试工具

yarn add redux-devtools-extension

combineReducers()

纯函数 ---- 同样的输入,得到同样的输出

不得修改参数    {...state, username: "test"}

不得调动 系统 I/O 的 API

不能调动不纯的 Date.now()  或者 Math.random() 等函数

高阶函数 ---- 参数是函数 或者 返回值是函数

filter、map、addEventListener、

高阶组件 ---- 函数接收一个组件,产生的新组件

connect

前端项目 和 后台服务器项目 各自独立运行

会产生 资源未找到 或者 跨域

  • 需要 后台工程师 进行代理服务器配置
  • 或者 将 前端项目 和 后台服务器项目 合并

前端项目 置于 后台服务器项目的 public

问题:

BrowserRouter 传递 state ---- 以致于访问 被置为后台路由处理了

解决:

自定义中间件处理

后台没有一个页面能够处理时,查看是否有前台页面可以返回

前台路由路径 不能与 后台路由路径 一样

专门的组件页面 应对 404 和 500 页面

react_结合 redux - 高阶函数 - 高阶组件 - 前端、后台项目打包运行的更多相关文章

  1. 高阶函数&&高阶组件(二)

    高阶组件总共分为两大类 代理方式 操纵prop 访问ref(不推荐) 抽取状态 包装组件 继承方式 操纵生命周期 操纵prop 代理方式之 操纵prop 删除prop import React fro ...

  2. javascript设计模式学习之三—闭包和高阶函数

    一.闭包 闭包某种程度上就是函数的内部函数,可以引用外部函数的局部变量.当外部函数退出后,如果内部函数依旧能被访问到,那么内部函数所引用的外部函数的局部变量就也没有消失,该局部变量的生存周期就被延续. ...

  3. Python中的高阶函数与匿名函数

    Python中的高阶函数与匿名函数 高阶函数 高阶函数就是把函数当做参数传递的一种函数.其与C#中的委托有点相似,个人认为. def add(x,y,f): return f( x)+ f( y) p ...

  4. Haskell学习-高阶函数

    原文地址:Haskell学习-高阶函数 高阶函数(higher-order function)就是指可以操作函数的函数,即函数可以作为参数,也可以作为返回结果.有了这两个特性,haskell可以实现许 ...

  5. JavaScript中的高阶函数

    之前写的<JavaScript学习手册>,客户跟我说有些内容不适合初学者,让我删了,感觉挺可惜的,拿到这里和大家分享. JavaScript中的一切都是对象,这句话同样适用于函数.函数对象 ...

  6. js 高阶函数 闭包

    摘自  https://www.cnblogs.com/bobodeboke/p/5594647.html 建议结合另外一篇关于闭包的文章一起阅读:http://www.cnblogs.com/bob ...

  7. spark快速开发之scala基础之5高阶函数,偏函数,闭包

    高阶函数 高阶函数就是将函数作为参数或者返回值的函数. object function { def main(args: Array[String]): Unit = { println(test(f ...

  8. 理解运用JS的闭包、高阶函数、柯里化

    JS的闭包,是一个谈论得比较多的话题了,不过细细想来,有些人还是理不清闭包的概念定义以及相关的特性. 这里就整理一些,做个总结. 一.闭包 1. 闭包的概念 闭包与执行上下文.环境.作用域息息相关 执 ...

  9. Python进阶:函数式编程(高阶函数,map,reduce,filter,sorted,返回函数,匿名函数,偏函数)...啊啊啊

    函数式编程 函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,这种分解可以称之为面向过程的程序设计.函数就是面向过程的程序设计 ...

随机推荐

  1. EF CodeFirst系列(2)---CodeFirst的数据库初始化

    1. CodeFirst的默认约定 1.领域类和数据库架构的映射约定 在介绍数据库的初始化之前我们需要先了解领域类和数据库之间映射的一些约定.在CodeFirst模式中,约定指的是根据领域类(如Stu ...

  2. HTML(三)HTML属性

    HTML 属性 属性: [class] 规定元素的一个或多个类 注意: 类不能以数字开头 class = "classA classB" // 多个类的写法 [id] 规定元素的唯 ...

  3. Spring IOC容器对bean的生命周期进行管理的过程

    1.通过构造器或者工厂方法创建bean的实例 2.为bean的属性设置值和对其他bean的引用 3.将bean的实例传递给bean的后置处理器BeanPostProcessor的postProcess ...

  4. [物理学与PDEs]第2章习题1 无旋时的 Euler 方程

    试证明: 当流场为无旋, 即 $\rot{\bf u}={\bf 0}$ 时, 理想流体的 Euler 方程可写为如下形式: $$\bex \cfrac{\p {\bf u}}{\p t}+\n \c ...

  5. 个人经验~ 利用5.7的sys库更好的排查问题

    一 简介:今天我们讲讲如何利用5.7的sys新库进行问题的排查二 描述   1 Sys库所有的数据源来自:performance_schema和information_schema.目标是把perfo ...

  6. 基于scrapy-redis分布式爬虫的部署

    redis分布式部署 1.scrapy框架是否可以自己实现分布式? - 不可以.原因有二. 其一:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器无法分配start_urls ...

  7. 【easy】226. Invert Binary Tree 反转二叉树

    /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode ...

  8. 【原创】大叔经验分享(10)Could not transfer artifact org.apache.maven:maven. from/to central. Received fatal alert: protocol_version

    maven编译工程报错 [ERROR] Failed to execute goal net.alchim31.maven:scala-maven-plugin:3.2.2:add-source (s ...

  9. ES6新语法

    ES6新语法概览 简介 ES6是JavaScript语言的新一代标准,加入了一些新的功能和语法,正式发布于2015年6月,亦称ES2015:该标准由ECMA(欧洲计算机制造联合会)的第39号技术专家委 ...

  10. Hadoop第一式:配置Linux环境

    所有操作在虚拟机下完成,虚拟机软件选用VMware Workstation Pro 12 (后文简称为VM) 关于Linux安装不再阐述一.网络环境配置 1)Windows界面 首先在VM页面,点击虚 ...