P07:通过Input体验Redux的流程

本文详细介绍了如何通过Redux管理React组件的状态,特别是当Input值改变时如何自动更新Store并触发组件更新。首先在TodoList组件中添加onChange事件,然后创建Action,通过dispatch将Action传给Store。接着在Reducer中处理Action,改变State。最后通过subscribe订阅Store变化,实现实时更新组件状态。同时,文章还涉及了AntDesign UI组件的使用和Chrome的Redux-DevTools插件安装。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

阐述

本文将要带大家作的就是通过 Input 的改变,体验一下 Redux 的整体流程,是如何编写代码的。我们要实现的是在 TodoListDemo 中,只要文本框中的值改变就 reduxstore 的值就跟着改变,并且随着 Redux 中的 state 值改变,组件也跟着改变。

整个流程就是以前讲过的这个图:
在这里插入图片描述

增加 Input 响应事件

如果想 Input 改变,redux 也跟着改变,需要在 Input 组件上增加 onChange 响应事件, 打开 src 目录下的 ToDolist.js 文件,修改具体代码如下:

<Input 
    placeholder={this.state.inputValue} 
    style={{ width:'250px', marginRight:'10px'}}
    //---------关键代码----start
    onChange={this.changeInputValue}
    //---------关键代码----end
/>

写完这一步,还要记得在 constructor 进行 this 的绑定,修改 this 的指向。

constructor(props){
    super(props)
    this.state=store.getState();
    this.changeInputValue= this.changeInputValue.bind(this)
}

这步完成后,就可以编写 changeInputValue 方法的代码了。
我们先在控制台打印出文本框的变化,代码如下:

changeInputValue(e){
    console.log(e.target.value)
}

然后打开浏览器,按F 12 看一下控制台的结果。

在这里插入图片描述
下面需要作的事就是改变 Redux 里的值了,我们继续向下学习。

源码

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.changeInputValue= this.changeInputValue.bind(this)
    }
    render() { 
        return ( 
            <div style={{margin:'10px'}}>
                <div>
                    <Input 
                        placeholder={this.state.inputValue} 
                        style={{ width:'250px', marginRight:'10px'}}
                        onChange={this.changeInputValue}
                    />
                    <Button type="primary">增加</Button>
                </div>
                <div style={{margin:'10px',width:'300px'}}>
                    <List
                        bordered
                        dataSource={this.state.list}
                        renderItem={item=>(<List.Item>{item}</List.Item>)}
                    />    
                </div>
            </div>
         );
    }

    changeInputValue(e){
        console.log(e.target.value)
    }
}
export default TodoList;

创建 Action

想改变 Redux 里边 State 的值就要创建 Action 了。

Action 就是一个对象,这个对象一般有两个属性,第一个是对Action的描述,第二个是要改变的值。

changeInputValue(e){
    const action ={
        type:'change_input_value',
        value:e.target.value
    }
}

action 就创建好了,但是要通过 dispatch() 方法传递给 store
我们在 action 下面再加入一句代码。

changeInputValue(e){
    const action ={
        type:'changeInput',
        value:e.target.value
    }
    store.dispatch(action)
}

这时 Action 就已经完全创建完成了,也和 store 有了联系。

store 的自动推送策略

前面的章节,已经说了 store 只是一个仓库,它并没有管理能力,它会把接收到的 action自动转发给Reducer

我们现在先直接在Reducer中打印出结果看一下。

打开 store 文件夹下面的 reducer.js 文件,修改代码。

export default (state = defaultState,action)=>{
    console.log(state,action)
    return state
}

讲到这里,就可以解释一下两个参数了:

state: 指的是原始仓库里的状态。
action: 指的是action新传递的状态。

通过打印你可以知道,Reducer已经拿到了原来的数据和新传递过来的数据,现在要作的就是改变 store 里的值。我们先判断 type 是不是正确的,如果正确,我们需要从新声明一个变量 newState(记住:Reducer里只能接收state,不能改变state。),所以我们声明了一个新变量,然后再次用return返回回去。

export default (state = defaultState,action)=>{
    if(action.type === 'changeInput'){
        let newState = JSON.parse(JSON.stringify(state)) //深度拷贝state
        newState.inputValue = action.value
        return newState
    }
    return state
}

在这里插入图片描述

让组件发生更新

现在 store 里的数据已经更新了,但是组件还没有进行更新,我们需要打开组件文件TodoList.js,在constructor,写入下面的代码。

constructor(props){
    super(props)
    this.state=store.getState();
    this.changeInputValue= this.changeInputValue.bind(this)
    //----------关键代码-----------start
    this.storeChange = this.storeChange.bind(this)  //转变this指向
    store.subscribe(this.storeChange) //订阅Redux的状态
    //----------关键代码-----------end
}

当然我们现在还没有这个 storeChange 方法,只要写一下这个方法,并且重新 setState一次就可以实现组件也是变化的。

在代码的最下方,编写 storeChange 方法。

storeChange(){
    this.setState(store.getState())
}

现在浏览器中预览,可以看到组件和Redux中都同步进行了改变。

总结

本文内容比较多,把Redux的流程都走了一遍,如果这节课你能独立作下来,也就算Redux入门了。

可以把本文内容多看两遍,保证把基础知识打扎实,更重要的是一定要动手作,不然你真的学不会的。

demo

初始化项目

1 如果你没有安装脚手架工具,你需要安装一下:

npm install -g create-react-app

2 直接用脚手架工具创建项目

D:  进入D盘
mkdir ReduxDemo           创建ReduxDemo文件夹
cd ReduxDemo              进入文件夹
create-react-app demo01   用脚手架创建React项目
cd demo01                 等项目创建完成后,进入项目目录
npm  start                预览项目

删除 src 里边的所有文件,只留一个 index.js,并且 index.js 文件里也都清空。

安装 Ant Design UI组件

Ant Design 是一套面向企业级开发的UI框架,视觉和动效作的很好。
安装 AntDesign

npm install antd --save

在使用Ant Design时,第一件事就是先引入CSS样式,有了样式才可以让UI组件显示正常。

import 'antd/dist/antd.css'

引入CSS样式之后,可以快乐的使用 antd 里的 <input> 框了,在使用的时候,你需要先引入Input组件。

import { Input } from 'antd'

Chrome 安装插件 Redux-DevTools

安装 Chrome 插件 Redux-DevTools – Redux调试工具
在这里插入图片描述

安装 Redux 是JavaScript应用工具

Redux是一个用来管理数据状态和UI状态的JavaScript应用工具。

在使用Redux之前,需要先用 npm install 来进行安装,打开终端,并进入到项目目录,然后输入。

npm install --save redux react-redux

在这里插入图片描述

Redux有3大核心概念:

  • Action
  • Reducer
  • Store

Action 和 Store 都非常好理解,我们可以直接按照其字面意思,将他们理解为 动作储存

Action表示应用中的各类动作或操作,不同的操作会改变应用相应的state状态,说白了就是一个带type属性的对象。

Store则是我们储存state的地方。
我们通过redux当中的createStore方法来创建一个store,它提供3个主要的方法:

import { createStore } from 'redux'  // 引入createStore方法
const store = createStore()          // 创建数据存储仓库
export default store                 //暴露出去

建立好了仓库,但是这个仓库很混乱,这时候就需要一个有管理能力的模块出现,这就是 Reducers。这两个一定要一起创建出来,这样仓库才不会出现互怼现象。

Reducer里更新Store里的state,Reducer接收两个参数:
旧的 state 和 Action,返回一个新的 state,即 (state, action) => newState

创建 Redux

安装好redux之后,在 src 目录下创建一个 store 文件夹,然后在文件夹下创建一个 index.js文件。

D:\ReactDemo\demo01\src\store\index.js 就是整个项目的 store 文件

D:\ReactDemo\demo01\src\store\index.js

//  引入createStore方法
import { createStore } from 'redux'

// reducer就建立好了后引入到 store 中,再创建 store 时,以参数的形式传递给 store。
import reducer from './reducer'

 // 创建数据存储仓库    
const store = createStore(
				reducer,
				// 配置 Redux Dev Tools
				window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
			  )
			  
export default store   //暴露出去

建立好了仓库,就需要 Reducers 管理模块。

D:\ReactDemo\demo01\src\store\reducer.js

const defaultState = {}  //默认数据
export default (state = defaultState,action)=>{  //就是一个方法函数
    return state
}

state: 是整个项目中需要管理的数据信息

项目目录结构

d/ReactDemo/demo01 (master)

$ ls -al
total 1921
drwxr-xr-x 1 Administrator 197121       0 12月  7 11:32 ./
drwxr-xr-x 1 Administrator 197121       0 12月  7 11:31 ../
drwxr-xr-x 1 Administrator 197121       0 12月  7 11:32 .git/
-rw-r--r-- 1 Administrator 197121     310 12月  7 11:31 .gitignore
drwxr-xr-x 1 Administrator 197121       0 12月 13 18:31 node_modules/
-rw-r--r-- 1 Administrator 197121     948 12月 13 18:31 package.json
-rw-r--r-- 1 Administrator 197121 1547406 12月 13 18:31 package-lock.json
drwxr-xr-x 1 Administrator 197121       0 12月  7 11:32 public/
-rw-r--r-- 1 Administrator 197121    3369 12月  7 11:31 README.md
drwxr-xr-x 1 Administrator 197121       0 12月 13 18:12 src/

d/ReactDemo/demo01/src/store (master)
 
$ ls -al
total 6
drwxr-xr-x 1 Administrator 197121   0 12月 13 18:14 ./
drwxr-xr-x 1 Administrator 197121   0 12月 13 18:12 ../
-rw-r--r-- 1 Administrator 197121 281 12月 13 19:14 index.js
-rw-r--r-- 1 Administrator 197121 430 12月 14 10:41 reducer.js

demo01\src\index.js

主文件

import React from 'react';
import ReactDOM from 'react-dom' // 上面两必有

import TodoList from './TodoList'

ReactDOM.render(<TodoList/>,document.getElementById('root'))

demo01\src\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.changeInputValue= this.changeInputValue.bind(this)
        //----------关键代码-----------start
        this.storeChange = this.storeChange.bind(this)  //转变this指向
        store.subscribe(this.storeChange) //订阅Redux的状态
        //----------关键代码-----------end
    }

    render() { 
        return ( 
            <div style={{margin:'10px'}}>
                <div>
                    <Input 
                        placeholder={this.state.inputValue} 
                        style={{ width:'250px', marginRight:'10px'}}
                        onChange={this.changeInputValue}
                    />
                    <Button type="primary">增加</Button>
                </div>
                <div style={{margin:'10px',width:'300px'}}>
                    <List
                        bordered
                        dataSource={this.state.list}
                        renderItem={item=>(<List.Item>{item}</List.Item>)}
                    />    
                </div>
            </div>
         );
    }

    changeInputValue(e){
        const action ={
            type:'change_input_value',
            value:e.target.value
        }
        store.dispatch(action)
    }

    storeChange(){
        this.setState(store.getState())
    }

}
export default TodoList;

demo01\src\store\index.js

store 仓库

//  引入createStore方法
import { createStore } from 'redux'
import reducer from './reducer'

// 创建数据存储仓库
const store = createStore(reducer,window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__())

//暴露出去
export default store

demo01\src\store\reducer.js

const defaultState = {
    inputValue : 'Write Something',
    list:[
        '早上4点起床,锻炼身体',
        '中午下班游泳一小时'
    ]
}

export default (state = defaultState,action)=>{
    if(action.type === 'changeInput'){
        let newState = JSON.parse(JSON.stringify(state)) //深度拷贝state
        newState.inputValue = action.value
        return newState
    }
    return state
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知其黑、受其白

喝个咖啡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值