Redux案例-基于Ant Design React
1.Ant Design介绍和环境初始化
Ant Design
是一套面向企业级开发的UI框架,视觉和动效作的很好。阿里开源的一套UI框架,它不只支持React
,还有ng
和Vue
的版本,我认为不论你的前端框架用什么,Ant Design
都是一个不错的选择。习惯性把AntDesign
简称为antd
。
官网地址:https://ant.design/index-cn
2.项目初始化
#安装脚手架工具
cnpm install -g create-react-app
create-react-app demo05-redux
cd demo05-redux
yarn start
3.生成基本代码结构
删除src下所有文件,创建index.js。
import React from "react";
import ReactDOM from 'react-dom'
import App from './App'ReactDOM.render(<App/>,document.getElementById('root'))
创建App.js。
import React, {Component} from "react";class App extends Component {render() {return (<div>Hello World</div>)}
}export default App;
3.安装Ant Design
cnpm install antd --save
#或
yarn add antd
4.使用Ant Design制作基础UI界面
引入CSS样式
import 'antd/dist/antd.css'
编写Input框和Button按钮
import React, {Component} from "react";
import 'antd/dist/antd.css'
import {Input,Button} from "antd";//需要什么组件,引入什么组件class App extends Component {render() {return (<div><div><Input placeholder={'karma'} style={{ width:'250px'}}/><Button type="primary">添加</Button></div></div>)}
}export default App;
添加List列表,首先我们需要在class外声明一个data数组
const data=['test1','test2','test3'
]
再在App.js中,引入List组件。
import {Input,Button,List} from "antd";//需要什么组件,引入什么组件
添加List组件。
import React, {Component} from "react";
import 'antd/dist/antd.css'
import {Input, Button, List} from "antd";//需要什么,引入什么const data = ['test1','test2','test3'
]class App extends Component {render() {return (<div><div><Input placeholder={'karma'} style={{width: '250px'}}/><Button type="primary">添加</Button></div>{/*主要代码*/}<div><ListbordereddataSource={data}renderItem={item => (<List.Item>{item}</List.Item>)}></List></div>{/*主要代码*/}</div>)}
}export default App;
5.创建Redux中的仓库-store和reducer
首先需要先安装Redux。
cnpm install --save redux
再在src目录下创建store目录,在store目录下创建index.js。
import { createStore } from 'redux' // 引入createStore方法
const store = createStore() // 创建数据存储仓库
export default store //暴露出去
再创建reducer.js在store目录下。
const defaultState = {} //默认数据
export default (state = defaultState,action)=>{ //就是一个方法函数//state: 是整个项目中需要管理的数据信息,这里我们没有什么数据,所以用默认空的来表示。return state
}
最后在store/index.js中引入reducer,再将reducer以参数的形式传递给createStore方法。
import {createStore} from "redux";
import reducer from "./reducer";
const store =createStore(reducer);
export default store;
仓库store
和reducer
都创建好了,可以初始化下App.js中的数据了,在reducer.js
文件的defaultState
对象中,加入两个属性:inputValue
和list
。
const defaultState = {inputValue: 'karma',list: ['test1','test2','test3']
} //默认数据
让App.js组件获取到store中初始化的数据,在组件引入store。
import store from './store'
#或者
import store from './store/index'
再在组件的构造函数中获取到数据,将它赋值给组件的state
,最后再将数据进行渲染。
import React, {Component} from "react";
import 'antd/dist/antd.css'
import {Input, Button, List} from "antd";//需要什么,引入什么
import store from "./store";class App extends Component {// 主要代码constructor(props) {super(props);this.state=store.getState();}// 主要代码render() {return (<div><div><Input placeholder={'karma'} style={{width: '250px'}}/><Button type="primary">添加</Button></div><div>{/*主要代码*/}<ListbordereddataSource={this.state.list}renderItem={item => (<List.Item>{item}</List.Item>)}></List>{/*主要代码*/}</div></div>)}
}
export default App;
6.通过Input体验Redux的流程
给Input添加onChange时间,并在构造函数中进行bind绑定。
##创建inputChange方法
changeInputValue(e){console.log(e.target.value)
}##Input添加onChange事件,并再添加一个Input框,用来获取到第一个Input值的变化情况
<Input placeholder={'karma'} style={{width: '250px'}} onChange={this.inputChange}/>
<Input value={this.state.inputValue} style={{width: '250px'}} onChange={this.inputChange}/>
##构造函数中,进行绑定
this.inputChange=this.inputChange.bind(this)
在changeInputValue方法中,创建Action交互动作。
inputChange(e) {const action = {type: 'inputChange',##获取到Input框的值value: e.target.value}##通过dispatch传递到store中store.dispatch(action)
}
然后在reducer.js中进行数据改变操作。
export default (state = defaultState, action) => { //就是一个方法函数//state: 是整个项目中需要管理的数据信息,这里我们没有什么数据,所以用默认的来表示。if (action.type==='inputChange'){//Reducer里只能接收state,不能改变state,所以我们进行深度拷贝let newState=JSON.parse(JSON.stringify(state))//深度拷贝newState.inputValue=action.valuereturn newState}return state
}
记住:Reducer里只能接收state,不能改变state。
接着我们需要使得组件发生更新,我们需要在App组件构造函数中添加store订阅。
constructor(props) {super(props);this.state = store.getState();this.inputChange = this.inputChange.bind(this)// 主要代码this.storeChange = this.storeChange.bind(this)store.subscribe(this.storeChange)// 主要代码
}##并添加storeChange方法,进行重新setState更新组件数据
storeChange() {this.setState(store.getState())
}
然后我们在浏览器第一个Input框中输入值,第二个Input也随着变化。
7.添加Button响应事件
首先我们给Button添加onClick点击事件,并在构造函数中进行绑定。
<Input value={this.state.inputValue} style={{width: '250px'}} onChange={this.inputChange}/>
<Button type="primary" onClick={this.addItem}>添加</Button>##构造函数中添加绑定
this.addItem = this.addItem.bind(this)##添加addItem方法,创建action,并通过dispatch将操作传递给store
addItem() {const action = {type: 'addItem'}store.dispatch(action)
}
然后我们在reducer.js进行list数据添加操作。
export default (state = defaultState, action) => { //就是一个方法函数//state: 是整个项目中需要管理的数据信息,这里我们没有什么数据,所以用默认的来表示。if (action.type === 'inputChange') {let newState = JSON.parse(JSON.stringify(state))//深度拷贝newState.inputValue = action.valuereturn newState}if (action.type === 'addItem') {let newState = JSON.parse(JSON.stringify(state))//深度拷贝newState.list.push(newState.inputValue)newState.inputValue = ''return newState}return state
}
最后我们就可以点击Button按钮进行List数据添加。
8.通过Redux进行List的删除
首先,我们需要给List子项绑定onClick事件,并传递下标进行绑定。
<ListbordereddataSource={this.state.list}renderItem={(item, index) => (<List.Item onClick={this.itemChange.bind(this, index)}>{item}</List.Item>)}></List>##添加删除方法,将action操作通过dispatch传递到store中deleteItem(index) {const action = {type: 'deleteItem',index}store.dispatch(action)}
再在reducer.js中,进行数据删除操作更新。
if (action.type === 'deleteItem') {let newState = JSON.parse(JSON.stringify(state))//深度拷贝newState.list.splice(action.index, 1)return newState
}
然后在浏览器中,我们就可以点击item子项,进行List数据删除。
9.把Action Type单独创建一个js文件管理
#创建store/actionTypes.js
export const CHANGE_INPUT='changeInput'
export const ADD_INFO='addInfo'
export const DELETE_ITEM='deleteItem'
export const GET_LIST='getList'
引入Action中使用
#actionTypes.js
import {CHANGE_INPUT, ADD_INFO, DELETE_ITEM} from './store/actionTypes'changeInput(e) {const action = {type: CHANGE_INPUT,value: e.target.value}store.dispatch(action)
}clickBtn() {const action = {type: ADD_INFO}store.dispatch(action)
}deleteItem(index) {const action = {type: DELETE_ITEM,index}store.dispatch(action)
}
引入Reducer并进行更改
#reducer.js
import {CHANGE_INPUT, ADD_INFO, DELETE_ITEM} from './actionTypes'if (action.type === CHANGE_INPUT) {let newState = JSON.parse(JSON.stringify(state))//深度拷贝statenewState.inputValue = action.valuereturn newState
}
if (action.type === ADD_INFO) {let newState = JSON.parse(JSON.stringify(state))//深度拷贝statenewState.list.push(newState.inputValue)newState.inputValue = ''return newState
}
if (action.type === DELETE_ITEM) {let newState = JSON.parse(JSON.stringify(state))//深度拷贝statenewState.list.splice(action.index, 1)return newState;
}
10.编写actionCreators.js
为了让action方便统一管理,使得代码更加简洁。
#actionCreators.js
import {CHANGE_INPUT, ADD_INFO, DELETE_ITEM, GET_LIST} from './actionTypes'export const changeInput = (value) => ({type: CHANGE_INPUT,value
})export const clickBtn = () => ({type: ADD_INFO
})export const deleteItem = (index) => ({type: DELETE_ITEM,index
})
在App.js中引入action常量方法
#App.js
import {changeInput, clickBtn, deleteItem} from './store/actionCreators'#方法修改
changeInput(e) {store.dispatch(changeInput(e.target.value))
}clickBtn() {store.dispatch(clickBtn())
}deleteItem(index) {store.dispatch(deleteItem(index))
}
11.Redux所遇到的坑
store
必须是唯一的,多个store
是坚决不允许,只能有一个store
空间- 只有
store
能改变自己的内容,Reducer
不能改变 Reducer
必须是纯函数
12.组建UI和业务拆分
拆分UI组件,首先我们先创建一个AppUI.js文件,将App.js中的JSX部分代码复制过来,并引入所需的相关组件
import React, {Component} from "react";
import 'antd/dist/antd.css'
import { Input , Button , List } from 'antd'
class AppUI extends Component {render() {return (<div style={{margin: '10px'}}><div><Input style={{width: '250px', marginRight: '10px'}}onChange={this.changeInput} value={this.state.inputValue}/><Button type={"primary"} onClick={this.clickBtn}>添加</Button></div><div><ListbordereddataSource={this.state.list}renderItem={(item, index) => (<List.Item onClick={this.deleteItem.bind(this, index)}>{item}</List.Item>)}/></div></div>)}
}export default AppUI;
修改App.js文件
#引入AppUI组件
import AppUI from "./AppUI";#并修改JSX部分代码
render() { return ( <AppUI />);
}
UI组件和业务逻辑组件整合
#App.jsconstructor(props) {super(props);this.state = store.getState();this.changeInput = this.changeInput.bind(this)this.clickBtn = this.clickBtn.bind(this)#需要在constructor(构造函数里)对deleteItem方法进行重新绑定thisthis.deleteItem = this.deleteItem.bind(this)this.storeChange = this.storeChange.bind(this)store.subscribe(this.storeChange)
}
render() {return (<AppUIchangeInput={this.changeInput}inputValue={this.state.inputValue}clickBtn={this.clickBtn}list={this.state.list}deleteItem={this.deleteItem}
/>);
}
#AppUI.js
import React, {Component} from "react";
import {Button, Input, List} from "antd";
import 'antd/dist/antd.css'
class AppUI extends Component {render() {return (<div style={{margin: '10px'}}><div><Input style={{width: '250px', marginRight: '10px'}}onChange={this.props.changeInput} value={this.props.inputValue}/><Button type={"primary"} onClick={this.props.clickBtn}>添加</Button></div><div><ListbordereddataSource={this.props.list}renderItem={(item, index) => (<List.Item onClick={() => this.props.deleteItem(index)}>{item}</List.Item>)}/></div></div>)}
}export default AppUI;
需要注意的是在List
组件的删除功能,需要用箭头函数的形式,代替以前方法,并在箭头函数里使用属性的方法,调用出啊你过来的方法。
<ListbordereddataSource={this.props.list}renderItem={(item,index)=>(<List.Item onClick={()=>{this.props.deleteItem(index)}}>{item}</List.Item>)}
/>
13.Redux中的无状态组件
- 首先我们不在需要引入React中的
{ Component }
,删除就好。 - 然后些一个
TodoListUI
函数,里边只返回JSX
的部分就好,这步可以复制。 - 函数传递一个
props
参数,之后修改里边的所有props
,去掉this
。
import React from "react";
import {Button, Input, List} from "antd";
import 'antd/dist/antd.css'const AppUI = (props) => {return (<div style={{margin: '10px'}}><div><Input style={{width: '250px', marginRight: '10px'}}onChange={props.changeInput} value={props.inputValue}/><Button type={"primary"} onClick={props.clickBtn}>添加</Button></div><div><ListbordereddataSource={props.list}renderItem={(item, index) => (<List.Item onClick={() => props.deleteItem(index)}>{item}</List.Item>)}/></div></div>)
}export default AppUI;
14.Axios异步获取list数据
利用easy-mock模拟数据
https://www.easy-mock.com/mock/5f96cc6134c55d14fda96ea1/example/query#自定义返回数据格式 {"success": true,"data": {"list": ["test1","test2","test3"]} }
安装并使用Axios
cnpm install --save axios
在App.js中引入axios,并在组件中声明周期函数
import axios from 'axios'#声明周期函数 componentDidMount
componentDidMount(){axios.get('https://www.easy-mock.com/mock/5f96cc6134c55d14fda96ea1/example/query').then((res)=>{console.log(res)})
}
将数据渲染传递给list,首先我们需要在store/actionCreators.js文件中,引入action常量,创建一个新的函数,
#actionTypes.js
export const GET_LIST='getList'#actionCreators.js
import {GET_LIST} from './actionTypes'
export const getList = (list) => ({type: GET_LIST,list
})
然后在App.js中引入函数,并将数据通过store.dispatch传递list值
import {getList} from './store/actionCreators'componentDidMount() {Axios.get('https://www.easy-mock.com/mock/5f96cc6134c55d14fda96ea1/example/query').then((res) => {console.log(res)store.dispatch(getList(res.data.data.list))})
}
最后在reducer.js中将值赋给list
#引入action常量
import {GET_LIST} from './actionTypes'#创建action事件
if (action.type === GET_LIST) {let newState = JSON.parse(JSON.stringify(state))//深度拷贝statecnewState.list=action.listreturn newState;
}
个人博客:Karma‘s Blog
源码地址:传送门
Redux案例-基于Ant Design React相关推荐
- React 基于ant design Pro 4 实现的一个分页, 自定义页码颜色
标题目录 代码 样式 前言 这是在 Ant Design Pro 4 中基于 ant design 的 Pagination 分页组件的基础上开发的. 有这么一个需求, 页码的颜色基于该页是否有差异, ...
- 基于Ant Design和jQuery UI的表单设计器
基于Ant Design 和jQuery UI 的表单设计器 GitHub 地址 概念 Comonent 组件 Layout 布局,一种特殊的Component Component Editor 组件 ...
- 基于Ant Design of Vue实现时长组件 duration
最近遇到一个需求,需要一个输入时长的组件,在经过一番寻找后没有合适的,最终自己动手写一个(实现了v-model双向绑定),记录一下,也给小伙伴们提供一个方便. 本示例基于ant design of v ...
- 基于Ant Design UI框架的React项目
概述 这款基于React开发的UI框架,界面非常简洁美观,在这篇文章中我主要为大家介绍一下如何用Ant开始搭建React项目 详细 代码下载:http://www.demodashi.com/demo ...
- 弹窗案例实现(Ant Design + React hooks)
Ant Design 是React里常用的UI框架 我们选用的是Ant Design 的 Modal 我们可以从Ant Design 官网看到一个基本的弹框大致长这个样子 一个弹框,大概需要弹框名称, ...
- Vue 2.x折腾记 - (16) 基于Ant Design Vue 封装一个配置式的表单搜索组件
前言 这次的后台管理系统项目选型用了Vue来作为主技术栈: 因为前段时间用过React来写过项目(用了antd),感觉棒棒的. 所以这次就排除了Element UI,而采用了Ant Design Vu ...
- 基于ant design pro的前后端分离的小型餐馆管理系统
安装配置 前端 下载代码 antDesignProLearning-front 安装依赖,在命令行输入命令npm install或yarn 官方推荐使用 tyarn 来进行包管理,可以极大地减少 in ...
- antd 日期选择框如何提交_基于Ant Design的Modal组件来实现一个可拖拽的React模态框...
引言 写这篇文章的原因是因为在项目中用到了Antd Design的React组件,当有业务需求需要用到模态框的时候遇到了一些小问题,Antd的模态框Modal组件时不能拖拽的,一般情况下不可拖拽也没什 ...
- 极客Go云监工 — 基于Ant Design的Web React实现
前言 玩客云接口的破解和后端api都已经分析了,那些都是看不见的,而展现在用户面前的是前端的web或者微信的小程序. 由于一开始还不会小程序就先用react写了一个前端,写的比较乱,将就能用,也没有系 ...
最新文章
- 12、Struts2表单重复提交
- Serverless 解惑——函数计算如何访问 Mongo 数据库
- Android studio 使用SVN需要忽略的文件
- webpack使用教程
- windows 下安装wamp环境
- 阿里十年DBA经验产品经理:真的不要再有一起删库跑路事件了
- MaxCompute Hash Clustering介绍
- 【Mac】Mac键盘实现Home, End, Page UP, Page DOWN
- winform布局、控件
- 2.吴恩达机器学习课程-作业2-逻辑回归
- 规则引擎drools java,spring,spring-boot,drools使用案例
- C语言实现可视化,运用EasyX实现拼图+文字解谜+迷宫+猜数游戏
- VS2019官方下载地址
- 计算机如何添加gust用户,win7系统如何创建安全的Guest账户
- 路由器linux+开机启动,路由器里设置FRP开机启动教程
- 软件工程——软件总体设计
- jarsigner签名APK完整步骤
- oracle 10g 与11g的几点常用区别
- MD5.js,前端MD5加密
- 新闻编辑室第三季/全集The Newsroom迅雷下载
热门文章
- 云南旅游最美景点20强最新排名
- 凸优化第四章凸优化问题 4.2凸优化
- P5278 算术天才⑨与等差数列 题解
- html怎么转换内联元素,css怎么将内联元素设成块元素?
- 【Java代码的运行过程】 ——每天一点小知识
- 游戏出海如何以低成本获取高收益?
- 2021 New Year‘s Resolution
- 数据结构java实验 刘小晶_数据结构实例解析与实验指导:Java语言描述
- 吃透Chisel语言.36.Chisel实战之以FIFO为例(一)——FIFO Buffer和Bubble FIFO的Chisel实现
- 远程访问服务器tensorboard