React:Redux简介

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

一、概念


1. 解决什么问题?

在这里插入图片描述

2. 基本概念

  1. Redux主要作用就是统一状态管理,将分散在各个组件中的状态全部放在统一的store对象中进行管理,适用于状态特别分散、状态共用较多、状态传递较深的情形。

  2. Redux 是一个提供可预测化状态管理的容器,主要包含store,reducer,action

① 应用中的 state 以对象树的形式存储在 store 中

② state是只读的,惟一改变 state 的方法就是触发 action

③ action 是一个用于描述已发生事件的普通对象

④ 通过 dispatch action来改变 state,描述 action如何改变 state 的函数叫 reducer

3. 分解

  1. action

可参考action设计规范, type,payload,error.meta,其中 type 是必须的

异步action,通过中间件实现

  1. reducer

reducer必须是纯函数

可以拆分成多个reducer, 通过combineReducers合并

  1. store

单一Store

根据reducer创建 store.createStore(reducer,initialState)

二、Redux工作流程


1. 图示

在这里插入图片描述

2. 步骤分解

store.dispatch(action);

let nextState = todoApp(previousState, action);

// 设置监听函数

store.subscribe(listener);

  1. listener可以通过store.getState()得到当前状态。如果使用的是 React,这时可以触发重新渲染 View

3. redux的原则

  1. state 是只读的,唯一修改它的方式是 actions

  2. 更新的唯一方式:dispatch(action) -> reducer -> new state

  3. Reducer 函数必须是“纯”的 —— 不能修改它的参数,也不能有副作用(不能对函数作用域之外的变量做任何更改。不要改变函数作用域以外的变量,不要调用其他会改变的函数,也不要dispatch actions等)

三、Redux改造TodoList


  1. 将分散在各个组件的状态统一放在store全局对象上,这样在每个组件需要状态时可以直接引入store取出状态,避免了状态之间的多层传递

  2. 对state的所有操作必须通过dispatch发出action给reducer,由reducer根据action的type对state进行操作并返回新的state,这使state的改变可容易追踪和可控

  3. 因为store是全局的,因此子组件不需要组件向父组件开放过多的接口(不需要传入那么多的变量给prop)

四、TodoList改造步骤


1. 目录结构规划

src |

-| commponents

-| store

App.js

index.css

index.js

store |

-| index.js

-| reducers.js

-| actionCreators

-| actionTypes

commponents |

-| Foot.jsx

-| Item.jsx

-| List.jsx

-| Top.jsx

2. store/index.js

  1. 说明:全局状态对象store创建和导出,它需要提供一个返回 state 的函数——reducers

import {createStore, applyMiddleware, compose} from ‘redux’

import reducers from ‘./reducers’

import ReduxThunk from ‘redux-thunk’

// 处理redux-thunk的兼容问题

const composeEnhancers =

typeof window === ‘object’ &&

window.REDUX_DEVTOOLS_EXTENSION_COMPOSE ?

window.REDUX_DEVTOOLS_EXTENSION_COMPOSE({}) : compose;

const enhancer = composeEnhancers(

applyMiddleware(ReduxThunk)

);

//创建store状态管理对象

const store = createStore(reducers, enhancer);

export default store;

3. store/actionTypes

  1. 说明:

① Action对象描述你想做出的改变或者将触发的事件,它必须带有一个type 属性,为action提供type描述(说明),约定action在reducers中的匹配,这个文件就是将所有的type定义为常量,避免编写时出错

② actionCreators中定义的每个回调函数返回的action对象上都有一个type属性,用以标识每个action

③ 在界面通过store.dispatch(action)(这里的action都是从actionCreators中引入的)派发到renducers时,renducers函数是通过actions.type来判断传过来的是哪个action

export const GET_ALL_ITEM = ‘get_all_item’; // 存TODO

export const CHANGE_TODO_ITEM = ‘change_todo_item’; // 修改一条TODO的选中状态

export const DEL_TODO_ITEM = ‘del_todo_item’; //删除一条TODO

export const ADD_TODO_ITEM = ‘add_todo_item’; //添加一条TODO

export const DEL_FINISHED_TODO_ITEM = ‘del_finished_todo_item’; //删除所有已经完成的TODO

export const IS_CHECKED_ALL_TODO_ITEM = ‘is_checked_all_todo_item’; //删除所有已经完成的TODO

4. store/actionCreators.js

  1. 说明:

① 这里定义了所有的action,通过回调函数的形式返回action对象,使用回调函数的目的是为了让界面组件可以调用

② 每个action都有一个type属性,它定义了该action的类型;同时接受一个参数,是界面组件需要的状态,由action带给reducer

③ 界面上调用这里定义的回调函数(返回一个对象,对象的第一个属性type是,第二个参数是从界面接收的参数),通过store.dispatch(action)将action派发到reducers,reducres根据action.type属性对state进行相应处理

④ action充当了界面与reducers的桥梁,将界面中组件需要的数据和对数据进行的处理传给renducers,由reducers负责更新state

import {

GET_ALL_ITEM,

CHANGE_TODO_ITEM,

DEL_TODO_ITEM,

ADD_TODO_ITEM,

DEL_FINISHED_TODO_ITEM,

IS_CHECKED_ALL_TODO_ITEM

} from ‘./actionTypes’

// 1. 存Todo

export const getAllItemAction = (todos)=>({

type: GET_ALL_ITEM,

todos

});

// 2. 单个TODO选中与否

export const getChangeItemFinishedAction = (todoId, flag)=>({

type: CHANGE_TODO_ITEM,

todoId,

flag

});

// 3. 单个TODO删除

export const getDelItemAction = (todoId)=>({

type: DEL_TODO_ITEM,

todoId

});

// 4. 添加一条记录

export const getAddItemAction = (todo)=>({

type: ADD_TODO_ITEM,

todo

});

// 5. 删除所有已经完成的记录

export const getRemoveFinishedItemAction = ()=>({

type: DEL_FINISHED_TODO_ITEM

});

// 6. 全选与非全选

export const getIsCheckedAllAction = (flag)=>({

type: IS_CHECKED_ALL_TODO_ITEM,

flag

});

5. store/reducers

  1. 说明:

① reducer 的职责是接收当前 state 和一个 action 然后返回新的 state

② 状态state以及操作状态的方法都在这里,符合了数据和操作数据的方法在同一个文件的原则

③ 根据在界面组件中通过store.dispatch(action)派发过来的action.type,匹配到相应的操作状态的方法,并根据组件传入的 参数,对state进行相应操作,将当前state直接进行替换,并合并旧的state返回给store

④ reducer是直接用新的state替换旧的state,而不是更新旧的state,就是说旧的state还是保留的;返回最新的state给界面组件,同时保留了新state和旧state存入store,使state可以回溯和方便进行时间旅行调试

import {

GET_ALL_ITEM,

CHANGE_TODO_ITEM,

DEL_TODO_ITEM,

ADD_TODO_ITEM,

DEL_FINISHED_TODO_ITEM,

IS_CHECKED_ALL_TODO_ITEM

} from ‘./actionTypes’

// 初始状态数据

const defaultState = {

todos: [],

finishedCount: 0

};

//根据action的type,对state进行相应操作,并返回新的state

export default (state = defaultState, action)=>{

console.log(state, action);

// 1. 存所有的Todo

if(action.type === GET_ALL_ITEM){

const newState = JSON.parse(JSON.stringify(state));

newState.todos = action.todos;

return newState;

}

// 2. 选中与取消选中

if(action.type === CHANGE_TODO_ITEM){

const newState = JSON.parse(JSON.stringify(state));

// 1. 遍历

let tempFinishedCount = 0;

newState.todos.forEach((todo, index)=>{

if(action.todoId === todo.id){

todo.finished = action.flag;

}

if(todo.finished){

tempFinishedCount += 1;

}

});

// 2. 返回一个新的状态

newState.finishedCount = tempFinishedCount;

return newState;

}

// 3. 单个TODO删除

if(action.type === DEL_TODO_ITEM){

const newState = JSON.parse(JSON.stringify(state));

// 1. 遍历

let tempFinishedCount = 0;

newState.todos.forEach((todo, index)=>{

if(action.todoId === todo.id){

newState.todos.splice(index, 1);

}

});

// 处理选中的

newState.todos.forEach((todo, index)=>{

if(todo.finished){

tempFinishedCount += 1;

}

});

// 2. 返回新状态

newState.finishedCount = tempFinishedCount;

return newState;

}

// 4. 添加一条记录

if(action.type === ADD_TODO_ITEM){

console.log(action);

const newState = JSON.parse(JSON.stringify(state));

newState.todos.push(action.todo);

return newState;

}

// 5. 删除所有已经完成的记录

if(action.type === DEL_FINISHED_TODO_ITEM){

const newState = JSON.parse(JSON.stringify(state));

let tempArr = [];

newState.todos.forEach((todo, index)=>{

if(!todo.finished){ // 没有完成的任务

tempArr.push(todo);

}

});

// 2. 返回新状态

newState.finishedCount = 0;

newState.todos = tempArr;

return newState;

}

// 6. 全选与非全选

if(action.type === IS_CHECKED_ALL_TODO_ITEM){

const newState = JSON.parse(JSON.stringify(state));

// 6.1. 遍历

let tempFinishedCount = 0;

newState.todos.forEach((todo, index)=>{

todo.finished = action.flag;

});

// 处理选中的

newState.todos.forEach((todo, index)=>{

if(todo.finished){

tempFinishedCount += 1;

}

});

// 6.2. 返回新状态

newState.finishedCount = tempFinishedCount;

return newState;

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

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

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

img

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

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

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

最后的最后

面试题千万不要死记,一定要自己理解,用自己的方式表达出来,在这里预祝各位成功拿下自己心仪的offer。
需要完整面试题的朋友可以点击蓝色字体获取

大厂面试题

面试题目录

img-u2a2EsAv-1712953156666)]

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

[外链图片转存中…(img-KOSHkCb9-1712953156667)]

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

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

最后的最后

面试题千万不要死记,一定要自己理解,用自己的方式表达出来,在这里预祝各位成功拿下自己心仪的offer。
需要完整面试题的朋友可以点击蓝色字体获取

[外链图片转存中…(img-Ou0nwlXv-1712953156667)]

[外链图片转存中…(img-2uWINOwr-1712953156667)]

[外链图片转存中…(img-N7EdwPwv-1712953156667)]

[外链图片转存中…(img-KSdQE9GD-1712953156668)]

  • 17
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值