redux从入门到进阶,看这一篇就够了!(代码片段)

星期一研究室 星期一研究室     2023-01-16     751

关键词:

🌂序言

大家都知道, react单向数据流,所以它传递数据也较为简单,父子之间的关系也较为明确。但是呢,如果我们要做更多复杂数据的传递,单单使用 react 是完全不够的。因此,我们需要用到 redux 来做更为复杂的数据传递。

那在下面的这篇文章中,将从入门到进阶,讲解 redux 的工作流程。

叮!开始 redux 之旅吧~👏

☂️一、基础知识

1、Redux概念简述

对于 react 来说,它是一个非视图层的轻量级框架,如果要用它来传递数据的话,则要先父传子,然后再慢慢地一层一层往上传递。

但如果用 redux 的话,假设我们想要某个组件的数据,那这个组件的数据则会通过 redux 来存放到 store 中进行管理。之后呢,通过 store ,再来将数据一步步地往下面的组件进行传递。

值得注意的是,我们可以视 ReduxReducerFlux 的结合。

2、Redux的工作流程

Redux ,实际上就是一个数据层的框架,它把所有的数据都放在了 store 之中。我们先来看一张图:

大家可以看到中间的 store ,它里面就存放着所有的数据。继续看 store 向下的箭头,然后呢,每个组件都要向 store 里面去拿数据。

我们用一个例子来梳理整张图,具体如下:

  • ①整张图上有一个 store ,它存放着所有的数据,也就是存储数据的公共区域
  • ②每个组件,都要从 store 里面拿数据;
  • ③假设现在有一个场景,模拟我们要在图书馆里面借书。那么我们可以把 react Component 理解为借书人,之后呢,借书人要去找图书馆管理员才能借到这本书。而借书这个过程中数据的传递,就可以把它视为是 Action Creators ,可以理解为 “你想要借什么书” 这句话。
  • Action Creatures 去到 store 。这个时候我们把 store 当做是图书馆管理员,但是,图书馆管理员是没有办法记住所有图书的数据情况的。一般来说,它都需要一个记录本,你想要借什么样的书,那么她就先查一下;又或者你想要还什么书,她也要查一下,需要放回什么位置上。
  • ⑤这个时候就需要跟 reducers 去通信,我们可以把 reducers 视为是一个记录本,图书馆管理员用这个记录本来记录需要的数据。管理员 store 通过 reducer 知道了应该给借书人 Components 什么样的数据。

🎃二、使用Antd实现TodoList页面布局

1、在项目中使用Antd

打开 antdesign 的官网👉antd官网传送门,我们先来在项目中引入它。具体步骤如下:

第一步,安装 antd命令如下:

npm install antd --save

第二步,引入样式。代码如下:

import 'antd/dist/antd.css'; // or 'antd/dist/antd.less'

2、使用Antd实现TodoList的基本布局

首先,我们在项目的 src 文件夹下创建一个新的文件,命名为 TodoList.js具体代码如下:

import React,  Component  from 'react';
import 'antd/dist/antd.css';
import  Input, Button, List  from 'antd';

const data = [
  'Racing car sprays burning fuel into crowd.',
  'Japanese princess to wed commoner.',
  'Australian walks 100km after outback crash.',
  'Man charged over missing wedding girl.',
  'Los Angeles battles huge wildfires.',
];

class TodoList extends Component 
  render() 
    return (
      <div style=marginTop: '10px', marginLeft: '10px'>
        <div>
          <Input placeholder="todo info" style= width: '300px'  />
          <Button type="primary">提交</Button>
        </div>
        <List
          bordered
          dataSource=data
          renderItem=item => <List.Item>item</List.Item>
        />
      </div>
    )
  


export default TodoList;

此时浏览器的显示效果为:

3、创建redux中的store

(1)创建store

接下来我们来创建项目中的 store 。首先在项目的 src 文件夹下创建一个新的文件夹,命名为 store 。接着,我们在 store 文件夹下面,创建一个新的文件,命名为 index.js具体代码如下:

import  createStore  from "redux";
import reducer from './reducer';

const store = createStore(reducer);

export default store;

然后呢,继续在 store 文件夹下面创建一个新的文件,命名为 reducer.js具体代码如下:

const defaultStore = 
  inputValue: '',
  list: []
;

export default (state = defaultStore, action) => 
  return state;

由此,我们就创建完成了项目中的 store

(2)在项目中使用store

创建完 store 之后,我们先初步在项目中使用这个 store ,以便于看看效果。先来添加 store 中的数据,首先改造在 store 中的 reducer.js 文件,具体代码如下:

const defaultStore = 
  inputValue: '123',
  list: [1, 2]
;

export default (state = defaultStore, action) => 
  return state;

之后改造 TodoList.js具体代码如下:

import React,  Component  from 'react';
import 'antd/dist/antd.css';
import  Input, Button, List  from 'antd';
import store from './store'; 

class TodoList extends Component 
  constructor(props) 
    super(props);
      this.state = store.getState()
  
  render() 
    return (
      <div style=marginTop: '10px', marginLeft: '10px'>
        <div>
          <Input placeholder=this.state.inputValue style= width: '300px'  />
          <Button type="primary">提交</Button>
        </div>
        <List
          bordered
          dataSource=this.state.list
          renderItem=item => <List.Item>item</List.Item>
        />
      </div>
    )
  


export default TodoList;

此时浏览器的显示效果为:

🧵三、Action和Reducer的编写 - 增添功能

1、主体页面内容改造

接下来,我们使用 actionreducer ,来对这个组件的数据进行前后传递。首先,先来改造 TodoList.js 文件。具体代码如下:

import React,  Component  from 'react';
import 'antd/dist/antd.css';
import  Input, Button, List  from 'antd';
import store from './store'; 

class TodoList extends Component 
  constructor(props) 
    super(props);
    this.state = store.getState()
    this.handleInputChange = this.handleInputChange.bind(this)
    this.handleStoreChange = this.handleStoreChange.bind(this)
    this.handleBtnClick = this.handleBtnClick.bind(this)
    store.subscribe(this.handleStoreChange)
  
  render() 
    return (
      <div style=marginTop: '10px', marginLeft: '10px'>
        <div>
          <Input
            value=this.state.inputValue
            placeholder="todo info"
            style= width: '300px', marginRight: '10px'
            onChange=this.handleInputChange
          />
          <Button type="primary" onClick=this.handleBtnClick>提交</Button>
        </div>
        <List
          style=marginTop: '10px', width: '300px'
          bordered
          dataSource=this.state.list
          renderItem=item => <List.Item>item</List.Item>
        />
      </div>
    )
  

  handleInputChange(e) 
    // 在react中,action是一个对象的形式
    // type旨在告诉react说,你帮我去改变input的值,这个值是下面的value,也就是e.target.value
    const action = 
      type: 'change_input_value',
      value: e.target.value
    
    store.dispatch(action)
    // console.log(e.target.value)
  

  handleStoreChange() 
    // 当感知到store的数据发生变化时,那么就去调用store.getState方法,从store里面再重新取一次数据,
    // 然后去调用setState,替换掉当前store里面的数据
    this.setState(store.getState())
  

  handleBtnClick() 
    const action = 
      type: 'add_todo_item'
    
    store.dispatch(action)
  


export default TodoList;

接下来我们来分析以上代码。首先,每一个动作分别会先去绑定对应的事件,之后呢,在事件里面,去创造 action 。而对于创造的 action 来说,它旨在告诉 react ,让 react 去帮忙 action 去改变某个值,而这个值就是它绑定的 value

最后, action 要做的事情结束了,那么它的数据就需要去存储到 store 里面。于是通过 store.dispatch(action) 来进行处理,将 action 的数据传递到 store 里面。

2、改变action中的数据

对于 action 一开始的值来说,它是固定的。但有时候我们是想要去修改action中的值,这个时候就需要用到 reducer 。现在,我们来改造下 reducer.js 文件,让 input 框可以自由的输入值,同时,点击提交按钮之后,进行列表的增添操作。具体代码如下:

const defaultStore = 
  inputValue: '123',
  list: [1, 2]
;

// reducer 可以接收state,但是绝不能修改state
const reducer = (state = defaultStore, action) => 
  if (action.type === 'change_input_value') 
    const newState = JSON.parse(JSON.stringify(state));
    newState.inputValue = action.value;
    return newState;
  
  if (action.type === 'add_todo_item') 
    const newState = JSON.parse(JSON.stringify(state));
    newState.list.push(newState.inputValue);
    newState.inputValue = '';
    console.log(newState);
    return newState;
  
  return state;

export default reducer;

3、store数据改造

下面,我们来看下 store 文件夹下 index.js 的内容。我们需要对其进行简单的改造,具体代码如下:

import  createStore  from "redux";
import reducer from './reducer';

const store = createStore(
  reducer,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

export default store;

除了 reducer 之外,我们还要将 window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__() 给传递进去并调用这个方法。

最后,我们来看下浏览器的显示效果:

🧶四、使用Redux实现TodoList的删除功能

1、对组件进行事件绑定

上面我们实现了增添功能,那么现在,我们继续来实现删除功能,实现每点击每一项时,能够删除点击项的数据。先来在 TodoList.js 文件中绑定对应的事件,具体代码如下:

import React,  Component  from 'react';
import 'antd/dist/antd.css';
import  Input, Button, List  from 'antd';
import store from './store'; 

class TodoList extends Component 
  constructor(props) 
    // 此处省略上述已有代码
  
  render() 
    return (
      /* 此处省略上述已有代码 */
        <List
          style=marginTop: '10px', width: '300px'
          bordered
          dataSource=this.state.list
          renderItem=(item, index) => <List.Item onClick=this.handleItemDelete.bind(this, index)>item</List.Item>
        />
      </div>
    )
  

  // 此处省略上述已有代码
  
  handleItemDelete(index) 
    const action = 
      type: 'delete_todo_item',
      index
    
    store.dispatch(action);
  


export default TodoList;

2、在reducer中进行数据通信

接着,我们在 reducer.js 文件中,对数据进行通信。具体代码如下:

const defaultStore = 
  inputValue: '123',
  list: [1, 2]
;

// reducer 可以接收state,但是绝不能修改state
const reducer = (state = defaultStore, action) => 
  // 此处省略上述已有代码
    
  if (action.type === 'delete_todo_item') 
    const newState = JSON.parse(JSON.stringify(state));
    newState.list.splice(action.index, 1);
    return newState;
  
  return state;

export default reducer;

现在,我们来看下浏览器的显示效果:

👓五、逻辑归纳

1、ActionTypes的拆分

在上面的 TodoList.js 中,大家可以看到,我们会频繁地去操作 action 。同时,假设说其中的 type 如果我们稍微写错了一个字母,那排错的过程总是不好定位的。

因此,我们要来做的一件事情就是 ActionTypes 的拆分。

首先,我们在 store 文件夹下新增一个文件,命名为 actionTypes.js具体代码如下:

export const CHANGE_INPUT_VALUE = 'change_input_value';
export const ADD_TODO_ITEM = 'add_todo_item';
export const DELETE_TODO_ITEM = 'delete_todo_item';

其次,改造 TodoList.js 下的内容。具体代码如下:

import 
  CHANGE_INPUT_VALUE,
  ADD_TODO_ITEM,
  DELETE_TODO_ITEM
 from './store/actionTypes'

class TodoList extends Component 

  handleInputChange(e) 
    const action = 
      type: CHANGE_INPUT_VALUE,
      value: e.target.value
    
    store.dispatch(action)
  

  handleStoreChange() 
    this.setState(store.getState())
  

  handleBtnClick() 
    const action = 
      type: ADD_TODO_ITEM
    
    store.dispatch(action)
   

  handleItemDelete(index) 
    const action = 
      type: DELETE_TODO_ITEM,
      index
    
    store.dispatch(action);
  


export default TodoList;

最后,改造 reducer.js 文件。具体代码如下:

import 
  CHANGE_INPUT_VALUE,
  ADD_TODO_ITEM,
  DELETE_TODO_ITEM
 from './actionTypes';

const defaultStore = 
  inputValue: '123',
  list: [1, 2]
;

const reducer = (state = defaultStore, action) => 
  if (action.type === CHANGE_INPUT_VALUE) 
    const newState = JSON.parse(JSON.stringify(state));
    newState.inputValue = action.value;
    return newState;
  
  if (action.type === ADD_TODO_ITEM) 
    const newState = JSON.parse(JSON.stringify(state));
    newState.list.push(newState.inputValue);
    newState.inputValue = '';
    console.log(newState);
    return newState;
  
  if (action.type === DELETE_TODO_ITEM) 
    const newState = JSON.parse(JSON.stringify(state));
    newState.list.splice(action.index, 1);
    return newState;
  
  return state;

export default reducer;

通过将 change_input_valueadd_todo_itemdelete_todo_item 进行整合,将其整合到 actionTypes.js 文件下,这样,如果我们遇到字母写错的情况下,也能够更好的进行排错。

2、使用actionCreator统一创建action

在上面的 TodoList.js 中,大家可以看到,对于几个绑定的事件来说,我们总是要频繁的去创建 action ,重复性

redux从入门到进阶,看这一篇就够了!(代码片段)

Redux,带你从入门到进阶🌂序言☂️一、基础知识1、Redux概念简述2、Redux的工作流程🎃二、使用Antd实现TodoList页面布局1、在项目中使用Antd2、使用Antd实现TodoList的基本布局3、创建redux中的store(1)创建storeÿ... 查看详情

docker从入门到精通,看这一篇就够了(代码片段)

一、Docker简介1、背景物理机时代一个物理机上安装操作系统,然后直接运行我们的软件。也就是说你电脑上直接跑了一个软件,并没有开虚拟机什么的,资源极其浪费。缺点部署慢成本高虚拟机都不开,直接上物... 查看详情

elasticsearch入门,看这一篇就够了(代码片段)

Elasticsearch入门,看这一篇就够了前言可视化工具kibanakibana的安装kibana配置kibana的启动Elasticsearch入门操作操作index创建index索引别名有什么用删除索引查询索引exist索引操作document插入document查询document删除document更新document使用... 查看详情

最全排序算法及优化,看这一篇就够了(代码片段)

...etCode题解:CSDN传送门有趣的CSS:Gitbook传送门前端进阶笔记:Gitbook传送门目录一、冒泡排序二、选择排序三、插入排序四、希尔排序五、归并排序六、快速排序一、冒 查看详情

vue3核心技能从入门到难点攻破,看这一篇就够了!

在Vue2.0时代,国内大厂的前端开发框架,几乎清一色偏向React。因为对于业务成熟的公司而言,一个项目,可能会包含很多非侵入式的代码和服务,并不是功能实现了就万事大吉。但随着Vue3.0横空出世,字... 查看详情

288页的python编程文档,从入门到实践,入门看这一篇就够了

Python是一门面向对象,解释型的高级程序设计语言,它的语法非常简洁、优雅,而这也是Python的一些设计哲学。Python自带了很完善的库,涵盖了数据库,网络,文件处理,GUI等方方面面,通过这些... 查看详情

史上最简明的tcpdump入门指南,看这一篇就够了(代码片段)

简介网络数据包截获分析工具。支持针对网络层、协议、主机、网络或端口的过滤。并提供and、or、not等逻辑语句帮助去除无用的信息。例子1、监听特定网卡tcpdump-ien02、监听特定主机例子:监听本机跟主机182.254.38.55之间往... 查看详情

json入门看这一篇就够了

什么是JSONJSON:JavaScriptObjectNotation【JavaScript对象表示法】JSON是存储和交换文本信息的语法。类似XML。JSON采用完全独立于任何程序语言的文本格式,使JSON成为理想的数据交换语言S为什么需要JSON提到JSON,我们就应该和XML来进行对... 查看详情

handler看这一篇就够了(代码片段)

Handler使用首先来熟悉一下Handler的四种使用方式,如果比较熟悉可以直接跳过:通过sendMessage消息机制来发送sendEmptyMessage(int);//发送一个空的消息sendMessage(Message);//发送消息,消息中可以携带参数sendMessageAtTime(Message,long... 查看详情

git入门看这一篇就够了!(转)(代码片段)

...文件,将快照永久性存储到Git仓库目录。 Git使用快速入门获取Git仓库 有两种取得Git项目仓库的方法。 在现有目录中初始化仓库:进入项目目录运行 gitinit 命令,该命令将创建一个名为 .git 的子目录。从... 查看详情

typescript与javascript的区别(typescript万字基础入门,了解ts,看这一篇就够了)(代码片段)

TypeScript是JavaScript的一个超集,支持ECMAScript6标准(ES6教程)。TypeScript由微软开发的自由和开源的编程语言。TypeScript设计目标是开发大型应用,它可以编译成纯JavaScript,编译出来的JavaScript可以运行在任何浏览... 查看详情

关于el-upload看这一篇就够了(代码片段)

下述源码分析基于Elementv2.15.9版本前提在解析源码之前,先阐述其重点使用的两个基础内容:<inputtype="file">使用type=“file”的元素使得用户可以选择一个或多个元素以提交表单的方式上传到服务器上,... 查看详情

关于el-upload看这一篇就够了(代码片段)

下述源码分析基于Elementv2.15.9版本前提在解析源码之前,先阐述其重点使用的两个基础内容:<inputtype="file">使用type=“file”的元素使得用户可以选择一个或多个元素以提交表单的方式上传到服务器上,... 查看详情

cas自旋锁,看这一篇就够了(代码片段)

前序时隔多年,杰伦终于出了新专辑,《最伟大的作品》让我们穿越到1920年,见到了马格利特的绿苹果、大利的超现实、常玉画的大腿、莫奈的睡莲、徐志摩的诗…他说“最伟大的作品”并不是自己的歌,而是这... 查看详情

css渐变背景看这一篇就够了(代码片段)

CSS渐变背景看这一篇就够了在我们自己设计网页的时候,为了好看美观,颜色可谓是最让人头疼的一部分。尤其是在配色上又找不到一些好看的网站。今天我就来记录一些好看的渐变式背景,和一些常用的颜色网站。... 查看详情

spring入门看这一篇就够了!!!不够你找我!

今天呢,咱就来点好家伙,前面都是些java基础,怎么说也得来点框架对吧,话不多说,煌sir带你开干!干就完了!  Spring框架一.Spring简述为什么要学spring?传统项目优点:搭建容易传统项目缺点:service、dao 对象都是程序员手动n... 查看详情

☀️javanio?看这一篇就够了!!☀️(代码片段)

文章目录一、NIO简介1.1NIO概述1.2NIO&IO分析1.2.1IO操作流程1.2.2面向流与面向缓冲区1.2.3阻塞与非阻塞1.2.4.同步与异步二、Buffer基本应用2.1Buffer概述2.2Buffer基本应用三、Channel基本应用3.1Channel概述3.2FileChannel基本应用3.3SocketChanel基... 查看详情

☀️javanio?看这一篇就够了!!☀️(代码片段)

文章目录一、NIO简介1.1NIO概述1.2NIO&IO分析1.2.1IO操作流程1.2.2面向流与面向缓冲区1.2.3阻塞与非阻塞1.2.4.同步与异步二、Buffer基本应用2.1Buffer概述2.2Buffer基本应用三、Channel基本应用3.1Channel概述3.2FileChannel基本应用3.3SocketChanel基... 查看详情