React(8)—— Redux - 三大核心概念 - store - reducer - actionn - Redux调试工具 - React-redux - 纯函数 - 高阶函数(1)

  1. 包含 2 个属性

type:标识属性, 值为字符串, 唯一, 必要属性

data:数据属性, 值类型任意, 可选属性

  1. 例子:{ type: 'ADD_STUDENT',data:{name: 'tom',age:18} }

三、API

========================================================================

1. createStore()


作用:创建包含指定reducerstore对象

2. store对象


  1. 作用: redux库最核心的管理对象

  2. 它内部维护着:

state

reducer

  1. 核心方法:

getState()

dispatch(action)

subscribe(listener)

  1. 具体编码:

store.getState()

store.dispatch({type:'INCREMENT', number})

store.subscribe(render)

3. applyMiddleware()


作用:应用上基于redux的中间件(插件库),Middleware 可以让你包装 store 的 dispatch 方法来达到你想要的目的,例如可以让store分发异步函数。

4. combineReducer()


作用:合并多个reducer函数


四、使用redux编写应用

================================================================================

1. 效果


在这里插入图片描述

2. 实现


redux/store.js

该文件专门用于暴露一个store对象,整个应用只有一个store对象

// 引入createStore,专门用于创建redux中最为核心的store对象

import { createStore } from “redux”;

// 引入为Count组件服务的reducer

import countReducer from “./count_reducer.js”;

// 暴露store

export default createStore(countReducer);

redux/count_reducer.js

该文件是用于创建一个为Count组件服务的reducer,reducer的本质就是一个函数

reducer函数会接到两个参数,分别为:之前的状态(preState),动作对象(action)

import {INCREMENT,DECREMENT} from ‘./constant’

const initState = 0 //初始化状态

export default function countReducer(preState=initState,action){

// console.log(preState);

//从action对象中获取:type、data

const {type,data} = action

//根据type决定如何加工数据

switch (type) {

case INCREMENT: //如果是加

return preState + data

case DECREMENT: //若果是减

return preState - data

default:

return preState

}

}

redux/count_action.js

该文件专门为Count组件生成action对象

import {INCREMENT,DECREMENT} from ‘./constant’

export const createIncrementAction = data => ({type:INCREMENT,data})

export const createDecrementAction = data => ({type:DECREMENT,data})

redux/constant.js

该文件专门为Count组件生成action对象

import {INCREMENT,DECREMENT} from ‘./constant’

export const createIncrementAction = data => ({type:INCREMENT,data})

export const createDecrementAction = data => ({type:DECREMENT,data})

Count/index.jsx

该模块是用于定义action对象中type类型的常量值,目的只有一个:便于管理的,同时防止程序员单词写错

export const INCREMENT = ‘increment’

export const DECREMENT = ‘decrement’

index.js

import React, { Component } from ‘react’

//引入store,用于获取redux中保存状态

import store from ‘…/…/redux/store’

//引入actionCreator,专门用于创建action对象

import {createIncrementAction,createDecrementAction} from ‘…/…/redux/count_action’

export default class Count extends Component {

/* componentDidMount(){

//检测redux中状态的变化,只要变化,就调用render

store.subscribe(()=>{

this.setState({})

})

} */

//加法

increment = ()=>{

const {value} = this.selectNumber

store.dispatch(createIncrementAction(value*1))

}

//减法

decrement = ()=>{

const {value} = this.selectNumber

store.dispatch(createDecrementAction(value*1))

}

//奇数再加

incrementIfOdd = ()=>{

const {value} = this.selectNumber

const count = store.getState()

if(count % 2 !== 0){

store.dispatch(createIncrementAction(value*1))

}

}

//异步加

incrementAsync = ()=>{

const {value} = this.selectNumber

setTimeout(()=>{

store.dispatch(createIncrementAction(value*1))

},500)

}

render() {

return (

当前求和为:{store.getState()}

<select ref={c => this.selectNumber = c}>

1 2 3

 

当前求和为奇数再加 

异步加 

)

}

}

index

import React from ‘react’

import ReactDOM from ‘react-dom’

import App from ‘./App’

import store from ‘./redux/store’

ReactDOM.render(,document.getElementById(‘root’))

// 监测redux中状态的改变,如redux的状态发生了改变,那么重新渲染App组件

store.subscribe(()=>{

ReactDOM.render(,document.getElementById(‘root’))

})

3. 总结


  1. store.js:

①引入redux中的createStore函数,创建一个store

②createStore调用时要传入一个为其服务的reducer

③记得暴露store对象

  1. count_reducer.js:

①reducer的本质是一个函数,接收:preState,action,返回加工后的状态

②reducer有两个作用:初始化状态,加工状态

③reducer被第一次调用时,是store自动触发的,传递的preState是undefined,传递的action是:{type:’@@REDUX/INIT_a.2.b.4}

  1. 在index.js中监测store中状态的改变,一旦发生改变重新渲染< App/ >

备注:redux只负责管理状态,至于状态的改变驱动着页面的展示,要靠我们自己写。

  1. 完整版新增文件:

count_action.js 专门用于创建action对象

constant.js 存放容易写错的type值

五、Redux异步编程

==============================================================================

1. 理解


  1. redux默认是不能进行异步处理的,

  2. 某些时候应用中需要在redux中执行异步任务(ajax, 定时器)

2.使用异步中间件


npm install redux-thunk

count_action.js

该模块专门为Count组件生成action对象

异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的

import{INCREMENT,DECREMENT} from ‘./constant’

//同步action,就是指action的值为Object类型的一般对象

export const createIncrementAction = data => ({type:INCREMENT,data})

export const createDecrementAction = data => ({type:DECREMENT,data})

//异步action,就是指action的值为函数,异步action中一般都会调用同步action,异步action不是必须要用的

export const createIncrementAsyncAction = (data,time) => {

return (dispatch)=>{

setTimeout(()=>{

dispatch(createIncrementAction(data))

},time)

}

}

store.js

该模块专门用于暴露一个store对象,整个应用只有一个store对象

在这里引入中间件

//引入createStore,专门用于创建redux中最为核心的store对象

import {createStore,applyMiddleware} from ‘redux’

//引入为Count组件服务的reducer

import countReducer from ‘./count_reducer’

//引入redux-thunk,用于支持异步action

import thunk from ‘redux-thunk’

//暴露store

export default createStore(countReducer,applyMiddleware(thunk))

3.总结


  1. 明确:延迟的动作不想交给组件自身,想交给action

  2. 何时需要异步action:想要对状态进行操作,但是具体的数据靠异步任务返回。

  3. 具体编码:

①npm install redux-thunk,并配置在store中

②创建action的函数不再返回一般对象,而是一个函数,该函数中写异步任务。

③异步任务有结果后,分发一个同步的action去真正操作数据。

  1. 备注:异步action不是必须要写的,完全可以自己等待异步任务的结果了再去分发同步action。

六、react-redux

================================================================================

1. 理解


  1. 一个React插件库

  2. 专门用来简化React应用中使用redux

2. react-redux将所有组件分成两大类


  1. UI组件

①只负责 UI 的呈现,不带有任何业务逻辑

②通过props接收数据(一般数据和函数)

③不使用任何 Redux 的 API

④一般保存在components文件夹下

  1. 容器组件

①负责管理数据和业务逻辑,不负责UI的呈现

②使用 Redux 的 API

③一般保存在containers文件夹下

模型图

在这里插入图片描述

3. 相关API


  1. Provider:让所有组件都可以得到state数据

  2. connect:用于包装 UI 组件生成容器组件

  3. mapStateToprops:将外部的数据(即state对象)转换为UI组件的标签属性

  4. mapDispatchToProps:将分发action的函数转换为UI组件的标签属性

4. 基本使用


安装

npm install react-redux

在这里插入图片描述

components/Count/index.jsx

UI组件

import React, { Component } from ‘react’

export default class Count extends Component {

//加法

increment = ()=>{

const {value} = this.selectNumber

this.props.jia(value*1)

}

//减法

decrement = ()=>{

const {value} = this.selectNumber

this.props.jian(value*1)

}

//奇数再加

incrementIfOdd = ()=>{

const {value} = this.selectNumber

if(this.props.count % 2 !== 0){

this.props.jia(value*1)

}

}

//异步加

incrementAsync = ()=>{

const {value} = this.selectNumber

this.props.jiaAsync(value*1,500)

}

render() {

//console.log(‘UI组件接收到的props是’,this.props);

return (

当前求和为:{this.props.count}

<select ref={c => this.selectNumber = c}>

1 2 3

 

当前求和为奇数再加 

异步加 

)

}

}

containers/Count/index.jsx

容器组件

//引入Count的UI组件

import CountUI from ‘…/…/components/Count’

//引入action

import {

createIncrementAction,

createDecrementAction,

createIncrementAsyncAction

} from ‘…/…/redux/count_action’

//引入connect用于连接UI组件与redux

import {connect} from ‘react-redux’

/*

1.mapStateToProps函数返回的是一个对象;

2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value

3.mapStateToProps用于传递状态

*/

function mapStateToProps(state){

return {count:state}

}

/*

1.mapDispatchToProps函数返回的是一个对象;

2.返回的对象中的key就作为传递给UI组件props的key,value就作为传递给UI组件props的value

3.mapDispatchToProps用于传递操作状态的方法

*/

function mapDispatchToProps(dispatch){

return {

jia:number => dispatch(createIncrementAction(number)),

jian:number => dispatch(createDecrementAction(number)),

jiaAsync:(number,time) => dispatch(createIncrementAsyncAction(number,time)),

}

}

//使用connect()()创建并暴露一个Count的容器组件

export default connect(mapStateToProps,mapDispatchToProps)(CountUI)

App.jsx

给容器组件传递store

import React, { Component } from ‘react’

import Count from ‘./containers/Count’

import store from ‘./redux/store’

export default class App extends Component {

render() {

return (

{/* 给容器组件传递store */}

)

}

}

总结

  1. 明确两个概念:

①UI组件:不能使用任何 redux 的api,只负责页面的呈现、交互等。

②容器组件:负责和 redux 通信,将结果交给UI组件。

  1. 如何创建一个容器组件————靠 react-redux 的 connect 函数

connect( mapStateToProps, mapDispatchToProps ) (UI组件)

mapStateToProps: 映射状态,返回值是一个对象

mapDispatchToProps: 映射操作状态的方法,返回值是一个对象

  1. 备注1:容器组件中的store是靠props传进去的,而不是在容器组件中直接引入

  2. 备注2:mapDispatchToProps,也可以是一个对象

5. 优化


优化1: 简写mapDispatchToProps

//使用connect()()创建并暴露一个Count的容器组件

export default connect(

state => ({count:state}),

//mapDispatchToProps的一般写法

/* dispatch => ({

jia:number => dispatch(createIncrementAction(number)),

jian:number => dispatch(createDecrementAction(number)),

jiaAsync:(number,time) => dispatch(createIncrementAsyncAction(number,time)),

}) */

//mapDispatchToProps的简写

{

jia:createIncrementAction,

jian:createDecrementAction,

jiaAsync:createIncrementAsyncAction,

}

)(CountUI)

优化2: Provider

容器组件可以检测redux中的状态改变,并渲染页面,所以不需要在index.js中检测了

不要在App.jsx中给子组件传递store了

index.js

import React from ‘react’

import ReactDOM from ‘react-dom’

import App from ‘./App’

import store from ‘./redux/store’

import {Provider} from ‘react-redux’

ReactDOM.render(

,

document.getElementById(‘root’)

)

优化3: 整合UI组件和容器组件

每个组件两个文件夹太麻烦了,直接整合在一起就好了!

containers/Count/index.jsx

import React, { Component } from ‘react’

//引入action

import {

createIncrementAction,

createDecrementAction,

createIncrementAsyncAction

} from ‘…/…/redux/count_action’

//引入connect用于连接UI组件与redux

import {connect} from ‘react-redux’

//定义UI组件

class Count extends Component {

state = {carName:‘奔驰c63’}

//加法

increment = ()=>{

const {value} = this.selectNumber

this.props.jia(value*1)

}

//减法

decrement = ()=>{

const {value} = this.selectNumber

this.props.jian(value*1)

}

//奇数再加

incrementIfOdd = ()=>{

const {value} = this.selectNumber

if(this.props.count % 2 !== 0){

this.props.jia(value*1)

}

}

//异步加

incrementAsync = ()=>{

const {value} = this.selectNumber

this.props.jiaAsync(value*1,500)

}

render() {

//console.log(‘UI组件接收到的props是’,this.props);

return (

当前求和为:{this.props.count}

<select ref={c => this.selectNumber = c}>

1 2 3

 

当前求和为奇数再加 

异步加 

)

}

}

//使用connect()()创建并暴露一个Count的容器组件

export default connect(

state => ({count:state}),

//mapDispatchToProps的一般写法

/* dispatch => ({

jia:number => dispatch(createIncrementAction(number)),

jian:number => dispatch(createDecrementAction(number)),

jiaAsync:(number,time) => dispatch(createIncrementAsyncAction(number,time)),

}) */

//mapDispatchToProps的简写

{

jia:createIncrementAction,

jian:createDecrementAction,

jiaAsync:createIncrementAsyncAction,

}

)(Count)

总结

  1. 容器组件和UI组件整合一个文件

  2. 无需自己给容器组件传递store,给< App/ >包裹一个< Provider store={store} >即可。

  3. 使用了react-redux后也不用再自己检测redux中状态的改变了,容器组件可以自动完成这个工作。

  4. mapDispatchToProps也可以简单的写成一个对象

  5. 一个组件要和redux“打交道”要经过哪几步?

①定义好UI组件 —— 不暴露

②引入connect生成一个容器组件,并暴露,写法如下:

connect(

state => ({key:value}), //映射状态

{key:xxxxxAction} //映射操作状态的方法

)(UI组件)

  1. 在UI组件中通过this.props.xxxxxxx读取和操作状态

6. 数据共享版


在这里插入图片描述

store.js

/*

该文件专门用于暴露一个store对象,整个应用只有一个store对象

*/

//引入createStore,专门用于创建redux中最为核心的store对象

import { createStore, applyMiddleware, combineReducers } from “redux”;

//引入为Count组件服务的reducer

import countReducer from “./reducers/count”;

//引入为Count组件服务的reducer

import personReducer from “./reducers/person”;

//引入redux-thunk,用于支持异步action

import thunk from “redux-thunk”;

// 汇总所有的reducer变为一个总的reducer

const allReducer = combineReducers({

he: countReducer,

rens: personReducer,

});

//暴露store

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

总结

  1. 定义一个Pserson组件,和Count组件通过redux共享数据。

  2. 为Person组件编写:reducer、action,配置constant常量。

  3. 重点:Person的reducer和Count的reducer要使用combineReducers进行合并,合并后的总状态是一个对象!

  4. 交给store的是总reducer。


七、使用上redux调试工具

=================================================================================

1. 安装chrome浏览器插件


Redux Dev Tools

2. 下载工具依赖包


npm install redux-devtools-extension

注意:安装完成之后一定要在store中进行配置过后才可使用

import {composeWithDevTools} from ‘redux-devtools-extension’

const store = createStore(allReducer,composeWithDevTools(applyMiddleware(thunk)))


八、纯函数和高阶函数

=============================================================================

reducer要求是一个纯函数,所以操作数组的时候,不能用push之类的方法

1. 纯函数


  1. 一类特别的函数: 只要是同样的输入(实参),必定得到同样的输出(返回)

  2. 必须遵守以下一些约束

①不得改写参数数据

②不会产生任何副作用,例如网络请求,输入和输出设备

③不能调用Date.now()或者Math.random()等不纯的方法

  1. reduxreducer函数必须是一个纯函数

2. 高阶函数


  1. 理解: 一类特别的函数

①情况1: 参数是函数

②情况2: 返回是函数

  1. 常见的高阶函数:

①定时器设置函数

②数组的forEach()/map()/filter()/reduce()/find()/bind()

③promise

④react-redux中的connect函数

  1. 作用: 能实现更加动态, 更加可扩展的功能

九、最终版

========================================================================

  • 所有变量名字要规范,尽量触发对象的简写形式。

  • reducers文件夹中,编写index.js专门用于汇总并暴露所有的reducer

在这里插入图片描述

containers/Count/index.jsx

import React, { Component } from ‘react’

//引入action

import {

increment,

decrement,

incrementAsync

} from ‘…/…/redux/actions/count’

//引入connect用于连接UI组件与redux

import {connect} from ‘react-redux’

//定义UI组件

class Count extends Component {

//加法

increment = ()=>{

const {value} = this.selectNumber

this.props.increment(value*1)

}

//减法

decrement = ()=>{

const {value} = this.selectNumber

this.props.decrement(value*1)

}

//奇数再加

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

javascript是前端必要掌握的真正算得上是编程语言的语言,学会灵活运用javascript,将对以后学习工作有非常大的帮助。掌握它最重要的首先是学习好基础知识,而后通过不断的实战来提升我们的编程技巧和逻辑思维。这一块学习是持续的,直到我们真正掌握它并且能够灵活运用它。如果最开始学习一两遍之后,发现暂时没有提升的空间,我们可以暂时放一放。继续下面的学习,javascript贯穿我们前端工作中,在之后的学习实现里也会遇到和锻炼到。真正学习起来并不难理解,关键是灵活运用。

资料领取方式:点击这里获取前端全套学习资料

css源码pdf

JavaScript知识点
ndex.jsx

import React, { Component } from ‘react’

//引入action

import {

increment,

decrement,

incrementAsync

} from ‘…/…/redux/actions/count’

//引入connect用于连接UI组件与redux

import {connect} from ‘react-redux’

//定义UI组件

class Count extends Component {

//加法

increment = ()=>{

const {value} = this.selectNumber

this.props.increment(value*1)

}

//减法

decrement = ()=>{

const {value} = this.selectNumber

this.props.decrement(value*1)

}

//奇数再加

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

[外链图片转存中…(img-Yb56heGa-1712952956195)]

[外链图片转存中…(img-A65FlCFb-1712952956195)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

[外链图片转存中…(img-RNm6hFXb-1712952956196)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

javascript是前端必要掌握的真正算得上是编程语言的语言,学会灵活运用javascript,将对以后学习工作有非常大的帮助。掌握它最重要的首先是学习好基础知识,而后通过不断的实战来提升我们的编程技巧和逻辑思维。这一块学习是持续的,直到我们真正掌握它并且能够灵活运用它。如果最开始学习一两遍之后,发现暂时没有提升的空间,我们可以暂时放一放。继续下面的学习,javascript贯穿我们前端工作中,在之后的学习实现里也会遇到和锻炼到。真正学习起来并不难理解,关键是灵活运用。

资料领取方式:点击这里获取前端全套学习资料

[外链图片转存中…(img-94UaAkMq-1712952956196)]

[外链图片转存中…(img-igZOzMDD-1712952956196)]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值