《React后台管理系统实战 :四》产品分类管理页:添加产品分类、修改(更新)产品分类

一、静态页面

目录结构

F:\Test\react-demo\admin-client\src\pages\admin\category

    add-cate-form.jsx
index.jsx
index.less
update-cate-form.jsx

1. pages/category/index.jsx

import React,{Component} from 'react'
import {
Button,
Card, //引入卡片
Table, //引入表格
Icon, } from 'antd';
import LinkButton from '../../../components/link-button' //引入自定义的链接样式按钮组件 export default class Category extends Component{
state={} render(){
//卡片标题
const title='产品分类管理'
//卡片右侧添加按键
const extra=(
<Button type='primary'>
<Icon type='plus'/>
添加
</Button>
) // 表格数据源示例
const dataSource = [
{
"parentId": "0",
"_id": "5c2ed631f352726338607046",
"name": "分类001",
"__v": 0
},
{
"parentId": "0",
"_id": "5c2ed647f352726338607047",
"name": "分类2",
"__v": 0
},
{
"parentId": "0",
"_id": "5c2ed64cf352726338607048",
"name": "1分类3",
"__v": 0
}
]; //表格列名
const columns = [
{
title: '分类名',
dataIndex: 'name',
key: 'name',
},
{
title: '操作',
width:'29%',
render: () => ( //向操作列所有行输出修改及查看分类两个按钮
<span>
<LinkButton>修改分类</LinkButton>
<LinkButton>查看子分类</LinkButton>
</span>
),
}, ]; return(
<div className='category'>
{/*卡片样式组件*/}
<Card title={title} extra={extra} >
{/*表格组件、边框、key为数据源的_id、数据源、列名定义*/}
<Table
bordered
rowKey='_id'
dataSource={dataSource}
columns={columns} />
</Card>
</div>
)
}
}

《React后台管理系统实战 :四》产品分类管理页:添加产品分类、修改(更新)产品分类

二、动态:产品分类数据请求

1.编写产品分类相关接口src/api/index.js

【1】获取产品一级/二级分类列表接口

【2】添加产品分类接口

【3】修改产品分类接口

import ajax from './ajax'
import jsonp from 'jsonp'
import {message} from 'antd' //借用antd返回信息组件
// const BASE = 'http://localhost:5000'
const BASE = '' //导出一个函数,第1种写法
//登录接口函数
// export function reqLogin(username,password){
// return ajax('login',{username,password},'POST')
// } //导出一个函数,第2种写法
// 登录接口函数
export const reqLogin=(username,password)=>ajax(BASE+'login',{username,password},'POST') //【1】获取产品一级/二级分类列表接口
export const reqCategorys=(parentId)=>ajax(BASE+'/manage/category/list',{parentId})
//【2】添加产品分类接口
export const reqAddCategory=(parentId,categoryName)=>ajax(BASE+'/manage/category/add',{parentId,categoryName},'POST')
//【3】修改产品分类接口
export const reqUpdateCategory=({parentId,categoryName})=>ajax(BASE+'/manage/category/update',{parentId,categoryName},'POST') // 天气接口
export const reqWeather=(city) => {
const url = `http://api.map.baidu.com/telematics/v3/weather?location=${city}&output=json&ak=3p49MVra6urFRGOT9s8UBWr2`
//返回一个promise函数
return new Promise((resolve,reject) => {
//发送一个jsonp请求
jsonp(url,{},(err,data) => {
//输出请求的数据到控制台
console.log('jsonp()', err, data)
//如果请求成功
if(!err && data.status==='success'){
//从数据中解构取出图片、天气
const {dayPictureUrl,weather}=data.results[0].weather_data[0]
//异步返回图片、天气给调用函数者
resolve({dayPictureUrl,weather})
}else{//如果请求失败
message.error('天气信息获取失败')
}
})
})
}
//reqWeather('上海')

2. 获取数据category/index.jsx

import React,{Component} from 'react'
import './index.less'
import {
Button,
Card,
Table,
Icon,
message,} from 'antd';
import LinkButton from '../../../components/link-button'
import {reqCategorys} from '../../../api/' //【1】获取api接口函数 export default class Category extends Component{
state={
categorys:[] //【2】存放api接口获取的分类列表
} //【3】异步请求一级分类列表
getCategorys = async (parentId)=>{
const result=await reqCategorys('0') //请求分类数据并赋值给result
if(result.status===0){ //如果返回的status=0,说明返回成功,执行:
const categorys=result.data //把返回数据赋值给categorys
console.log(result.data) //测试输出返回的数据
this.setState({
categorys //把返回的数据赋值给state里
})
}else{
message.error('获取分类失败')
}
} //【4】初始化表格column列名函数
initColumn=()=>{
//表格列名
this.columns = [
{
title: '分类名子',
key: 'name',
dataIndex: 'name',
},
{
title: '操作',
width:'29%',
render: () => (
<span>
<LinkButton>修改分类</LinkButton>
<LinkButton>查看子分类</LinkButton>
</span>
),
}, ];
} // 【5】页面完成加载后运行,用于异步加载等函数存放
componentDidMount(){
this.getCategorys() //获取表格数据源
} // 【6】页面将要加载运行:用于页面渲染前的数据准备
componentWillMount(){
this.initColumn() //准备表格列名相关数据
} render(){
//卡片标题
const title='产品分类管理'
//卡片右侧添加按键
const extra=(
<Button type='primary'>
<Icon type='plus'/>
添加
</Button>
) // 【7】对state里数据解构
const {categorys}=this.state return(
<div className='category'>
{/*卡片样式组件*/}
<Card title={title} extra={extra} >
{/*
【8】表格组件、边框、key为数据源的_id、数据源、列名定义
*/}
<Table
bordered
rowKey='_id'
dataSource={categorys}
columns={this.columns} />
</Card>
</div>
)
}
}

效果同一.1

3. 优化:加载数据动画、分页显示

【1】控制是否显示加载动画

【2】设置加载中动画状态显示

【3】数据加载完成,取消loading动画显示

【4】对state里数据解构

【5】分页配置:每页显示数量,显示快速跳转

【6】加载动画、

import React,{Component} from 'react'
import './index.less'
import {
Button,
Card,
Table,
Icon,
message,} from 'antd';
import LinkButton from '../../../components/link-button'
import {reqCategorys} from '../../../api/' //获取api接口函数 export default class Category extends Component{
state={
loading:false, //【1】控制是否显示加载动画
categorys:[] //存放api接口获取的分类列表
} //异步请求一级分类列表
getCategorys = async (parentId)=>{
this.setState({loading:true}) //【2】设置加载中动画状态显示
const result=await reqCategorys('0') //请求分类数据并赋值给result
if(result.status===0){ //如果返回的status=0,说明返回成功,执行:
const categorys=result.data //把返回数据赋值给categorys
console.log(result.data) //测试输出返回的数据
this.setState({
categorys, //把返回的数据赋值给state里
loading:false, //【3】数据加载完成,取消loading动画显示
})
}else{
message.error('获取分类失败')
}
} //初始化表格column列名函数
initColumn=()=>{
//表格列名
this.columns = [
{
title: '分类名子',
key: 'name',
dataIndex: 'name',
},
{
title: '操作',
width:'29%',
render: () => (
<span>
<LinkButton>修改分类</LinkButton>
<LinkButton>查看子分类</LinkButton>
</span>
),
},
];
} // 页面完成加载后运行,用于异步加载等函数存放
componentDidMount(){
this.getCategorys() //获取表格数据源
} // 页面将要加载运行:用于页面渲染前的数据准备
componentWillMount(){
this.initColumn() //准备表格列名相关数据
} render(){
//卡片标题
const title='产品分类管理'
//卡片右侧添加按键
const extra=(
<Button type='primary'>
<Icon type='plus'/>
添加
</Button>
) // 【4】对state里数据解构
const {categorys,loading}=this.state return(
<div className='category'>
{/*卡片样式组件*/}
<Card title={title} extra={extra} >
{/*
表格组件、边框、key为数据源的_id、
数据源、列名定义、
【5】分页配置:每页显示数量,显示快速跳转
【6】加载动画、
*/}
<Table
bordered
rowKey='_id'
dataSource={categorys}
columns={this.columns}
loading={loading}
pagination={{defaultPageSize: 5, showQuickJumper: true}}
/>
</Card>
</div>
)
}
}

效果:加载时显示加载中动画、每页显示5条数据(默认十条)

三、二级产品分类及面包屑

3.1 点一级分类进入对应子分类列表,

3.2 头部加面包屑,在子页面显示对应首页分类名

【1】初始为0即请求一级产品分类列表

【2】当前子分类的对应父分类名

【3】子分类列表数据

【4】parentId等于传进来的参数或state里的值

【5】把0改为从state内动态获取,请求分类数据并赋值给result

【6】如果parentId=0则是一级列表,执行:

【7】否则是二级列表,执行:

【8】数据源、如果parentId为0设置一级分类列表为数据源、否则二级分类为列表源

【9.0】参数:当前条目的数据对象,返回需要显示的界面标签

【9.1】添加事件监听点击时调用显示函数

因为如果加括号及参数就会自动执行函数,而不是点击后才执行,所以用一个匿名函数把它包起来

如果parentId=0即是父级列表则显示查看子分类按钮,否则什么也不显示

【10】显示一级分类对应二级产品分类函数

【11】先更新状state的parentId为对应新分类的id

【12】setState是异步执行,并不会马上更新完状态,

因此需在其内部写(在状态更新且重新render()后执行)

【20】卡片标题,如果是一及分类显示 一级分类列表,否则显示一级分类+链接+对应的一级分类名

【21】显示一级分类函数,设置id状态即可

import React,{Component} from 'react'
import './index.less'
import {
Button,
Card,
Table,
Icon,
message,} from 'antd';
import LinkButton from '../../../components/link-button'
import {reqCategorys,reqAddCategory} from '../../../api/' //获取api接口函数 export default class Category extends Component{
state={
loading:false, //控制是否显示加载动画
parentId:'0', //【1】初始为0即请求一级产品分类列表
categorys:[], //存放api接口获取的分类列表
parentName:'', //【2】当前子分类的对应父分类名
subCategorys:[], //【3】子分类列表数据 } //异步请求一级分类列表
getCategorys = async (parentId)=>{
this.setState({loading:true}) //设置加载中动画状态显示
parentId=parentId || this.state.parentId //【4】parentId等于传进来的参数或state里的值
const result=await reqCategorys(parentId) //【5】把0改为从state内动态获取,请求分类数据并赋值给result
if(result.status===0){ //如果返回的status=0,说明返回成功,执行:
console.log(result.data) //测试输出返回的数据
const categorys=result.data //把返回数据赋值给categorys //【6】如果parentId=0则是一级列表,执行:
if(parentId==='0'){
this.setState({
categorys, //(因为名称和state标签名相同,所以用简写)把返回的一级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
}else{//【7】否则是二级列表,执行:
this.setState({
subCategorys:categorys, //把返回的二级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
} }else{
message.error('获取分类列表失败')
}
} //【10】显示一级分类对应二级产品分类函数
showSubCategory=(category)=>{
//【11】先更新状state的parentId为对应新分类的id
this.setState({
parentId:category._id,
parentName:category.name
},()=>{/*【12】setState是异步执行,并不会马上更新完状态,
因此需在其内部写(在状态更新且重新render()后执行)*/
console.log('parentId',this.state.parentId)
this.getCategorys()//获取二级分类列表
}) }
//【21】显示一级分类函数,设置id状态即可
showCategorys=()=>{
this.setState({
parentId:'0',
parentName:'',
subCategorys:[],
})
}
//初始化表格column列名函数
initColumn=()=>{
//表格列名
this.columns = [
{
title: '分类名',
key: 'name',
dataIndex: 'name',
},
{
title: '操作',
width:'29%',
render: (categoryObj) => (//【9.0】参数:当前条目的数据对象,返回需要显示的界面标签
<span>
<LinkButton>修改分类</LinkButton>
{/*
【9.1】添加事件监听点击时调用显示函数
因为如果加括号及参数就会自动执行函数,而不是点击后才执行,所以用一个匿名函数把它包起来
如果parentId=0即是父级列表则显示查看子分类按钮,否则什么也不显示
*/}
{this.state.parentId==='0'?<LinkButton onClick={()=>this.showSubCategory(categoryOjb)}>查看子分类</LinkButton>:null}
</span>
),
}, ];
} //添加分类
addCate= async (parentId,categoryName)=>{
const result = await reqAddCategory(parentId,categoryName)
if(result.status===0){
message.success('分类数据添加成功')
}else{
message.error('添加分类失败')
}
} // 页面完成加载后运行,用于异步加载等函数存放
componentDidMount(){
this.getCategorys() //获取表格数据源
} // 页面将要加载运行:用于页面渲染前的数据准备
componentWillMount(){
this.initColumn() //准备表格列名相关数据
//this.addCate('5e41578325a557082c18f43b','洗衣机')
} render(){
// 对state里数据解构
const {categorys,subCategorys, parentId,parentName,loading}=this.state //【20】卡片标题,如果是一及分类显示 一级分类列表,否则显示一级分类+链接+对应的一级分类名
const title= parentId==='0'?'一级分类列表':(
<span>
<LinkButton onClick={this.showCategorys}>一级分类列表</LinkButton> >>
<span>{parentName}</span>
</span>
)
//卡片右侧添加按键
const extra=(
<Button type='primary'>
<Icon type='plus'/>
添加
</Button>
) return(
<div className='category'>
{/*卡片样式组件*/}
<Card title={title} extra={extra} >
{/*
表格组件、边框、key为数据源的_id、
【8】数据源、如果parentId为0设置一级分类列表为数据源、否则二级分类为列表源
列名定义、
一页显示数据条数,显示快速跳转
*/}
<Table
bordered
rowKey='_id'
dataSource={parentId==='0'? categorys:subCategorys}
columns={this.columns}
loading={loading}
pagination={{defaultPageSize: 5, showQuickJumper: true}}
/>
</Card>
</div>
)
}
}

效果:http://localhost:3000/category

《React后台管理系统实战 :四》产品分类管理页:添加产品分类、修改(更新)产品分类

四、添加分类、更新分类基础布局

4.1引进对话框、添加函数框架

【1】引入对话框

【2】添加分类、更新分类显示状态,0:都不显示,1:显示添加,2:显示更新

【3】对state里数据解构:

【4】添加对话框:0:都不显示,1:显示添加分类,2:显示更新分类

【5】添加监听函数:addCate,updateCate,handleCancel

【6】添加分类函数

【7】更新分类函数updateCate

【8】取消对话框函数handleCancel

【9】添加监听updateCate

【10】卡片右侧添加按键:添加监听

import React,{Component} from 'react'
import './index.less'
import {
Button,
Card,
Table,
Icon,
Modal, //【1】引入对话框
message,} from 'antd';
import LinkButton from '../../../components/link-button'
import {reqCategorys,reqAddCategory} from '../../../api/' //获取api接口函数 export default class Category extends Component{
state={
loading:false, //控制是否显示加载动画
parentId:'0', //初始为0即请求一级产品分类列表
categorys:[], //存放api接口获取的分类列表
parentName:'', //当前子分类的对应父分类名
subCategorys:[], //子分类列表数据
showStatus:0, //【2】添加分类、更新分类显示状态,0:都不显示,1:显示添加,2:显示更新
} //异步请求一级分类列表
getCategorys = async (parentId)=>{
this.setState({loading:true}) //设置加载中动画状态显示
parentId=parentId || this.state.parentId //parentId等于传进来的参数或state里的值
const result=await reqCategorys(parentId) //把0改为从state内动态获取,请求分类数据并赋值给result
if(result.status===0){ //如果返回的status=0,说明返回成功,执行:
console.log(result.data) //测试输出返回的数据
const categorys=result.data //把返回数据赋值给categorys //如果parentId=0则是一级列表,执行:
if(parentId==='0'){
this.setState({
categorys, //(因为名称和state标签名相同,所以用简写)把返回的一级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
}else{//否则是二级列表,执行:
this.setState({
subCategorys:categorys, //把返回的二级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
} }else{
message.error('获取分类列表失败')
}
} //显示一级分类对应二级产品分类函数
showSubCategory=(category)=>{
//先更新状state的parentId为对应新分类的id
this.setState({
parentId:category._id,
parentName:category.name
},()=>{/*setState是异步执行,并不会马上更新完状态,
因此需在其内部写(在状态更新且重新render()后执行)*/
console.log('parentId',this.state.parentId)
this.getCategorys()//获取二级分类列表
}) } //显示一级分类函数,设置id状态即可
showCategorys=()=>{
this.setState({
parentId:'0',
parentName:'',
subCategorys:[],
})
} //初始化表格column列名函数
initColumn=()=>{
//表格列名
this.columns = [
{
title: '分类名',
key: 'name',
dataIndex: 'name',
},
{
title: '操作',
width:'29%',
render: (categoryObj) => (//参数:当前条目数据对象,用于返回需要显示的界面标签
<span>
{/*【9】添加监听showUpdateCate */}
<LinkButton onClick={this.showUpdateCate}>修改分类</LinkButton>
{/*
添加事件监听点击时调用显示函数
因为如果加括号及参数就会自动执行函数,而不是点击后才执行,所以用一个匿名函数把它包起来
如果parentId=0即是父级列表则显示查看子分类按钮,否则什么也不显示
*/}
{this.state.parentId==='0'?<LinkButton onClick={()=>this.showSubCategory(categoryOjb)}>查看子分类</LinkButton>:null}
</span>
),
}, ];
} //【6】显示添加分类
showAddCate=()=>{
this.setState({
showStatus:1
})
}
//【7】显示更新分类showUp,
showUpdateCate=()=>{
this.setState({
showStatus:2
})
}
//【8】取消对话框函数handleCancel
handleCancel=()=>{
this.setState({
showStatus:0
})
} // 页面完成加载后运行,用于异步加载等函数存放
componentDidMount(){
this.getCategorys() //获取表格数据源
} // 页面将要加载运行:用于页面渲染前的数据准备
componentWillMount(){
this.initColumn() //准备表格列名相关数据
//this.addCate('5e41578325a557082c18f43b','洗衣机')
} render(){
// 【3】对state里数据解构:
const {categorys,subCategorys, parentId,parentName,loading,showStatus}=this.state //卡片标题,如果是一及分类显示 一级分类列表,否则显示一级分类+链接+对应的一级分类名
const title= parentId==='0'?'一级分类列表':(
<span>
<LinkButton onClick={this.showCategorys}>一级分类列表</LinkButton> >>
<span>{parentName}</span>
</span>
)
//【10】卡片右侧添加按键:添加监听
const extra=(
<Button type='primary' onClick={this.addCate}>
<Icon type='plus'/>
添加
</Button>
) return(
<div className='category'>
{/*卡片样式组件*/}
<Card title={title} extra={extra} >
{/*
表格组件、边框、key为数据源的_id、
数据源、如果parentId为0设置一级分类列表为数据源、否则二级分类为列表源
列名定义、
一页显示数据条数,显示快速跳转
*/}
<Table
bordered
rowKey='_id'
dataSource={parentId==='0'? categorys:subCategorys}
columns={this.columns}
loading={loading}
pagination={{defaultPageSize: 5, showQuickJumper: true}}
/> {/*【4】添加对话框:0:都不显示,1:显示添加分类,2:显示更新分类
【5】添加监听函数:addCate,updateCate,handleCancel */}
<Modal
title="添加分类"
visible={showStatus===1}
onOk={this.addCate}
onCancel={this.handleCancel}
>
<p>添加分类</p>
</Modal> <Modal
title="修改分类"
visible={showStatus===2}
onOk={this.updateCate}
onCancel={this.handleCancel}
>
<p>修改分类</p>
</Modal> </Card>
</div>
)
}
}

4.2编写添加分类界面pages/category/add-cate-form

import React,{Component} from 'react'
import {
Form,
Select,
Input
} from 'antd' const Item=Form.Item
const Option=Select.Option class AddCateForm extends Component{ render(){
return(
<Form>
<Item>
<span>所属分类:</span>
<Select>
<Option value='1'>一级分类</Option>
</Select>
</Item> <Item>
<span>添加子分类:</span>
<Input type='text' placeholder='请输入子分类名称' />
</Item> </Form>
)
}
}
export default AddCateForm;

pages/category/index.jsx引入刚写的组件

【20】添加分类表单

【21】使用<AddCateForm组件

import AddCateForm from './add-cate-form';//【20】添加分类表单

......

{/*添加对话框:0:都不显示,1:显示添加分类,2:显示更新分类
添加监听函数:addCate,updateCate,handleCancel
【21】使用<AddCateForm组件
*/}
<Modal
title="添加分类"
visible={showStatus===1}
onOk={this.addCate}
onCancel={this.handleCancel}
>
<AddCateForm />
</Modal>

4.4 表单返回数值获取知识点

官网文档:https://ant.design/components/form-cn/#Form.create(options)

improt {Form} from 'antd'
const {categorys, parentId} = this.props
const { getFieldDecorator } = this.props.form {
getFieldDecorator('parentId',{
initialValue:parentId
})(//要获取表单值的标签)
} {
getFieldDecorator('categoryName',{
rules:[
{required:true,message:'分类名称必须输入'}
]
})(
<Input type='text' placeholder='请输入子分类名称' />
)
}
exprot default Form.create()(组件名)

完整代码add-cate-form.jsx

import React,{Component} from 'react'
import {
Form,
Select,
Input
} from 'antd' const Item=Form.Item
const Option=Select.Option class AddCateForm extends Component{ render(){
const {categorys, parentId} = this.props
const { getFieldDecorator } = this.props.form
return(
<Form>
<Item>
<span>所属分类:</span>
{
getFieldDecorator('parentId',{
initialValue:parentId
})(
<Select>
<Option value='1'>一级分类</Option>
</Select>
)
} </Item> <Item>
<span>添加子分类:</span>
{
getFieldDecorator('categoryName',{
rules:[
{required:true,message:'分类名称必须输入'}
]
})( <Input type='text' placeholder='请输入子分类名称' />
)
} </Item> </Form>
)
}
}
export default Form.create()(AddCateForm);

4.5编写修改分类界面pages/category/update-cate-form.jsx

到此和4.4代码相同,换个类名即可

import React,{Component} from 'react'
import {
Form,
Select,
Input
} from 'antd' const Item=Form.Item
const Option=Select.Option class UpdateCateForm extends Component{ render(){
const {categorys, parentId} = this.props
const { getFieldDecorator } = this.props.form
return(
<Form>
<Item>
<span>所属分类:</span>
{
getFieldDecorator('parentId',{
initialValue:parentId
})(
<Select>
<Option value='1'>一级分类</Option>
</Select>
)
} </Item> <Item>
<span>添加子分类:</span>
{
getFieldDecorator('categoryName',{
rules:[
{required:true,message:'分类名称必须输入'}
]
})( <Input type='text' placeholder='请输入子分类名称' />
)
} </Item> </Form>
)
}
}
export default Form.create()(UpdateCateForm);

4.6效果:http://localhost:3000/category

《React后台管理系统实战 :四》产品分类管理页:添加产品分类、修改(更新)产品分类

五、修改产品分类功能实现

1.点击修改分类时自动显示对应的分类名pages/category/index.jsx

【1】在updateCateForm组件加一个参数categoryName用于传给子组件, 实现更新时显示当前条目的产品分类名称

【2】把当前条目的数据对象传递给updateCate函数

【3】接收[2]传来的对应条目数据对象

【4】接收参数赋值到当前函数

【5】把4步收到的参数赋值给categoryObj

【6】转到update-cate-form.jsx内接收传过来的参数categoryName

import React,{Component} from 'react'
import './index.less'
import {
Button,
Card,
Table,
Icon,
Modal, //引入对话框
message,} from 'antd';
import LinkButton from '../../../components/link-button'
import {reqCategorys,reqAddCategory} from '../../../api/' //获取api接口函数
import AddCateForm from './add-cate-form'; //添加分类表单
import UpdateCateForm from './update-cate-form'; //导入更新分类的表单 export default class Category extends Component{
state={
loading:false, //控制是否显示加载动画
parentId:'0', //初始为0即请求一级产品分类列表
categorys:[], //存放api接口获取的分类列表
parentName:'', //当前子分类的对应父分类名
subCategorys:[], //子分类列表数据
showStatus:0, //添加分类、更新分类显示状态,0:都不显示,1:显示添加,2:显示更新
} //异步请求一级分类列表
getCategorys = async (parentId)=>{
this.setState({loading:true}) //设置加载中动画状态显示
parentId=parentId || this.state.parentId //parentId等于传进来的参数或state里的值
const result=await reqCategorys(parentId) //把0改为从state内动态获取,请求分类数据并赋值给result
if(result.status===0){ //如果返回的status=0,说明返回成功,执行:
console.log(result.data) //测试输出返回的数据
const categorys=result.data //把返回数据赋值给categorys //如果parentId=0则是一级列表,执行:
if(parentId==='0'){
this.setState({
categorys, //(因为名称和state标签名相同,所以用简写)把返回的一级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
}else{//否则是二级列表,执行:
this.setState({
subCategorys:categorys, //把返回的二级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
} }else{
message.error('获取分类列表失败')
}
} //显示一级分类对应二级产品分类函数
showSubCategory=(category)=>{
//先更新状state的parentId为对应新分类的id
this.setState({
parentId:category._id,
parentName:category.name
},()=>{/*setState是异步执行,并不会马上更新完状态,
因此需在其内部写(在状态更新且重新render()后执行)*/
console.log('parentId',this.state.parentId)
this.getCategorys()//获取二级分类列表
}) } //显示一级分类函数,设置id状态即可
showCategorys=()=>{
this.setState({
parentId:'0',
parentName:'',
subCategorys:[],
})
} //初始化表格column列名函数
initColumn=()=>{
//表格列名
this.columns = [
{
title: '分类名',
key: 'name',
dataIndex: 'name',
},
{
title: '操作',
width:'29%',
render: (categoryObj) => (//category代表当前条目对象(名字随意),用于返回需要显示的界面标签
<span>
{/*【2】把当前条目的数据对象传递给showUpdateCate函数 */}
<LinkButton onClick={()=>this.showUpdateCate(categoryObj)}>修改分类</LinkButton>
{/*
添加事件监听点击时调用显示函数
因为如果加括号及参数就会自动执行函数,而不是点击后才执行,所以用一个匿名函数把它包起来
如果parentId=0即是父级列表则显示查看子分类按钮,否则什么也不显示
*/}
{this.state.parentId==='0'?<LinkButton onClick={()=>{this.showSubCategory(categoryObj)}}>查看子分类</LinkButton>:null}
</span>
),
}, ];
} //添加分类函数
addCate= async (parentId,categoryName)=>{
this.setState({
showStatus:1
})
// const result = await reqAddCategory(parentId,categoryName)
// if(result.status===0){
// message.success('分类数据添加成功')
// }else{
// message.error('添加分类失败')
// }
} //更新分类函数showUpdateCate,【3】接收[2]传来的对应条目数据对象
showUpdateCate=(categoryObj)=>{
//【4】接收参数赋值到当前函数
this.categoryObj=categoryObj
this.setState({
showStatus:2
})
} //取消对话框函数handleCancel
handleCancel=()=>{
this.setState({
showStatus:0
})
} // 页面完成加载后运行,用于异步加载等函数存放
componentDidMount(){
this.getCategorys() //获取表格数据源
} // 页面将要加载运行:用于页面渲染前的数据准备
componentWillMount(){
this.initColumn() //准备表格列名相关数据
//this.addCate('5e41578325a557082c18f43b','洗衣机')
} render(){
// 对state里数据解构:
const {categorys,subCategorys, parentId,parentName,loading,showStatus}=this.state
//【5】把4步收到的参数赋值给categoryObj
const categoryOjb = this.categoryObj || {} // 如果还没有,则指定一个空对象 //卡片标题,如果是一及分类显示 一级分类列表,否则显示一级分类+链接+对应的一级分类名
const title= parentId==='0'?'一级分类列表':(
<span>
<LinkButton onClick={this.showCategorys}>一级分类列表</LinkButton> >>
<span>{parentName}</span>
</span>
)
//卡片右侧添加按键:添加监听
const extra=(
<Button type='primary' onClick={this.addCate}>
<Icon type='plus'/>
添加
</Button>
) return(
<div className='category'>
{/*卡片样式组件*/}
<Card title={title} extra={extra} >
{/*
表格组件、边框、key为数据源的_id、
数据源、如果parentId为0设置一级分类列表为数据源、否则二级分类为列表源
列名定义、
一页显示数据条数,显示快速跳转
*/}
<Table
bordered
rowKey='_id'
dataSource={parentId==='0'? categorys:subCategorys}
columns={this.columns}
loading={loading}
pagination={{defaultPageSize: 5, showQuickJumper: true}}
/> {/*添加对话框:0:都不显示,1:显示添加分类,2:显示更新分类
添加监听函数:addCate,updateCate,handleCancel
使用<AddCateForm组件 */}
<Modal
title="添加分类"
visible={showStatus===1}
onOk={this.addCate}
onCancel={this.handleCancel}
>
<AddCateForm />
</Modal> {/*
【1】在updateCateForm组件加一个参数categoryName用于传给子组件,
实现更新时显示当前条目的产品分类名称
【6】转到update-cate-form.jsx内接收传过来的参数categoryName
*/}
<Modal
title="修改分类"
visible={showStatus===2}
onOk={this.updateCate}
onCancel={this.handleCancel}
>
<UpdateCateForm categoryName={categoryOjb.name}/>
</Modal> </Card>
</div>
)
}
}

2.接收父组件传过来的属性值,实现显示对应条目的类名update-cate-from.jsx

【1】接收父组件传值组件

【2】把从父组件接收过来的属性参数接收过来

【3】把categoryName解构出来

【4】文本框默认值为父组件传过来的对应条目数据的名字

import React,{Component} from 'react'
import {
Form,
Select,
Input
} from 'antd'
import PropTypes from 'prop-types' //【1】接收父组件传值组件 const Item=Form.Item
const Option=Select.Option class UpdateCateForm extends Component{
//【2】把从父组件接收过来的属性参数接收过来
static propTypes={
categoryName:PropTypes.string.isRequired,
} render(){
//【3】把categoryName解构出来
const {categoryName} = this.props
const { getFieldDecorator } = this.props.form
return(
<Form>
<Item>
{/**因为getFiledDecorator接收的标签必须为Form标签,因此span必须拿出来 */}
<span>修改分类名:</span>
{
getFieldDecorator('categoryName',{
//【4】文本框默认值为父组件传过来的对应条目数据的名字
initialValue:categoryName,
rules:[
{required:true,message:'分类名称必须输入'}
]
})( <Input type='text' placeholder='请输入子分类名称' />
)
} </Item> </Form>
)
}
}
export default Form.create()(UpdateCateForm);

效果:

《React后台管理系统实战 :四》产品分类管理页:添加产品分类、修改(更新)产品分类

3.执行修改产品分类

  1. 知识点,子向父组件传值
  2. form.resetFields()清除缓存

3.1 pages/category/index.jsx

【0】onOk点执行updateCate函数执行分类名修改

【1】执行修改分类(点对话框的ok按钮执行此函数)

【2】从子组件update-cate-form.jsx组件获取要修改的分类名

【3】接收子组件传来的form对象(向子组件传递带参数的函数,子组件调用它,再把from对象通过参数传回来)子组件把form对象传来之前,将其赋值到this.from里

【4】下接update-cate-form.jsx

【5】更新函数:重置所有表单数据,防止使用缓存,造成点其它条目时展示上一条修改的数据

【5】取消修改函数:重置所有表单数据,防止使用缓存,造成点其它条目时展示上一条修改的数据

import React,{Component} from 'react'
import './index.less'
import {
Button,
Card,
Table,
Icon,
Modal, //引入对话框
message,} from 'antd';
import LinkButton from '../../../components/link-button'
import {reqCategorys,reqAddCategory,reqUpdateCategory} from '../../../api/' //获取api接口请求函数
import AddCateForm from './add-cate-form'; //添加分类表单
import UpdateCateForm from './update-cate-form'; //导入更新分类的表单 export default class Category extends Component{
state={
loading:false, //控制是否显示加载动画
parentId:'0', //初始为0即请求一级产品分类列表
categorys:[], //存放api接口获取的分类列表
parentName:'', //当前子分类的对应父分类名
subCategorys:[], //子分类列表数据
showStatus:0, //添加分类、更新分类显示状态,0:都不显示,1:显示添加,2:显示更新
} //异步请求一级分类列表
getCategorys = async (parentId)=>{
this.setState({loading:true}) //设置加载中动画状态显示
parentId=parentId || this.state.parentId //parentId等于传进来的参数或state里的值
const result=await reqCategorys(parentId) //把0改为从state内动态获取,请求分类数据并赋值给result
if(result.status===0){ //如果返回的status=0,说明返回成功,执行:
console.log(result.data) //测试输出返回的数据
const categorys=result.data //把返回数据赋值给categorys //如果parentId=0则是一级列表,执行:
if(parentId==='0'){
this.setState({
categorys, //(因为名称和state标签名相同,所以用简写)把返回的一级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
}else{//否则是二级列表,执行:
this.setState({
subCategorys:categorys, //把返回的二级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
} }else{
message.error('获取分类列表失败')
}
} //显示一级分类对应二级产品分类函数
showSubCategory=(category)=>{
//先更新状state的parentId为对应新分类的id
this.setState({
parentId:category._id,
parentName:category.name
},()=>{/*setState是异步执行,并不会马上更新完状态,
因此需在其内部写(在状态更新且重新render()后执行)*/
console.log('parentId',this.state.parentId)
this.getCategorys()//获取二级分类列表
}) } //显示一级分类函数,设置id状态即可
showCategorys=()=>{
this.setState({
parentId:'0',
parentName:'',
subCategorys:[],
})
} //初始化表格column列名函数
initColumn=()=>{
//表格列名
this.columns = [
{
title: '分类名',
key: 'name',
dataIndex: 'name',
},
{
title: '操作',
width:'29%',
render: (categoryObj) => (//category代表当前条目对象(名字随意),用于返回需要显示的界面标签
<span>
{/*把当前条目的数据对象传递给updateCate函数 */}
<LinkButton onClick={()=>this.showUpdateCate(categoryObj)}>修改分类</LinkButton>
{/*
添加事件监听点击时调用显示函数
因为如果加括号及参数就会自动执行函数,而不是点击后才执行,所以用一个匿名函数把它包起来
如果parentId=0即是父级列表则显示查看子分类按钮,否则什么也不显示
*/}
{this.state.parentId==='0'?<LinkButton onClick={()=>{this.showSubCategory(categoryObj)}}>查看子分类</LinkButton>:null}
</span>
),
}, ];
} //显示添加分类函数
showAddCate= async (parentId,categoryName)=>{
this.setState({
showStatus:1
})
} //更新分类函数updateCate,接收[2]传来的对应条目数据对象
showUpdateCate=(categoryObj)=>{
//接收参数赋值到当前函数
this.categoryObj=categoryObj
this.setState({
showStatus:2
})
} //取消对话框函数handleCancel
handleCancel=()=>{
//【6】重置所有表单数据,防止上一条数据修改后点取消,下一条使用缓存,点其它条目时展示上一条修改的数据
this.form.resetFields()
this.setState({
showStatus:0
})
} //执行添加分类
AddCate= async (parentId,categoryName)=>{ const result = await reqAddCategory(parentId,categoryName)
if(result.status===0){
message.success('产品分类添加成功')
}else{
message.error('产品分类添加失败')
}
} //【1】执行修改分类(点对话框的ok按钮执行此函数)
updateCate= async ()=>{
//1.点ok后隐藏对话框
this.setState({showStatus:0})
//2.准备数据
const categoryId=this.categoryObj._id
//【2】从子组件update-cate-form.jsx组件获取要修改的分类名
const categoryName=this.form.getFieldValue('categoryName') //取this的form对象
// console.log('categoryId:',categoryId)
// console.log('categoryName:',categoryName)
//【5】重置所有表单数据,防止使用缓存,造成点其它条目时展示上一条修改的数据
this.form.resetFields()
//3.发送请求更新分类
const result = await reqUpdateCategory({categoryId,categoryName}) if(result.status===0){
message.success('产品分类修改名称成功')
//4.重新显示修改名称后的分类列表
this.getCategorys()
}else{
message.error('产品分类修改名称失败')
}
} // 页面完成加载后运行,用于异步加载等函数存放
componentDidMount(){
this.getCategorys() //获取表格数据源
} // 页面将要加载运行:用于页面渲染前的数据准备
componentWillMount(){
this.initColumn() //准备表格列名相关数据
//this.addCate('5e41578325a557082c18f43b','洗衣机')
} render(){
// 对state里数据解构:
const {categorys,subCategorys, parentId,parentName,loading,showStatus}=this.state
//把4步收到的参数赋值给categoryObj
const categoryOjb = this.categoryObj || {} // 如果还没有,则指定一个空对象 //卡片标题,如果是一及分类显示 一级分类列表,否则显示一级分类+链接+对应的一级分类名
const title= parentId==='0'?'一级分类列表':(
<span>
<LinkButton onClick={this.showCategorys}>一级分类列表</LinkButton> >>
<span>{parentName}</span>
</span>
)
//卡片右侧添加按键:添加监听
const extra=(
<Button type='primary' onClick={this.showAddCate}>
<Icon type='plus'/>
添加
</Button>
) return(
<div className='category'>
{/*卡片样式组件*/}
<Card title={title} extra={extra} >
{/*
表格组件、边框、key为数据源的_id、
数据源、如果parentId为0设置一级分类列表为数据源、否则二级分类为列表源
列名定义、
一页显示数据条数,显示快速跳转
*/}
<Table
bordered
rowKey='_id'
dataSource={parentId==='0'? categorys:subCategorys}
columns={this.columns}
loading={loading}
pagination={{defaultPageSize: 5, showQuickJumper: true}}
/> {/*添加对话框:0:都不显示,1:显示添加分类,2:显示更新分类
添加监听函数:addCate,updateCate,handleCancel
使用<AddCateForm组件 */}
<Modal
title="添加分类"
visible={showStatus===1}
onOk={this.addCate}
onCancel={this.handleCancel}
>
<AddCateForm />
</Modal> {/*
在updateCateForm组件加一个参数categoryName用于传给子组件,
实现更新时显示当前条目的产品分类名称
转到update-cate-form.jsx内接收传过来的参数categoryName
【0】onOk点执行updateCate函数执行分类名修改
*/}
<Modal
title="修改分类"
visible={showStatus===2}
onOk={this.updateCate}
onCancel={this.handleCancel}
>
{/*【3】接收子组件传来的form对象(向子组件传递带参数的函数,子组件调用它,再把from对象通过参数传回来)
子组件把form对象传来之前,将其赋值到this.from里
【4】下接update-cate-form.jsx*/}
<UpdateCateForm
categoryName={categoryOjb.name}
setForm={(form)=>{this.form=form}}
/>
</Modal> </Card>
</div>
)
}
}

3.2 update-cate-form.jsx

【1】设置setForm类型为函数且必须

【2】在此组件渲染之前调用一次setForm函数,把form传到父组件去

import React,{Component} from 'react'
import {
Form,
Select,
Input
} from 'antd'
import PropTypes from 'prop-types' //接收父组件传值组件 const Item=Form.Item
const Option=Select.Option class UpdateCateForm extends Component{
//把从父组件接收过来的属性参数接收过来
static propTypes={
categoryName:PropTypes.string.isRequired,
//【1】设置setForm类型为函数且必须
setForm:PropTypes.func.isRequired,
} //【2】在此组件渲染之前调用一次setForm函数,把form传到父组件去
componentWillMount(){
//将form对象通过setForm函数传给父组件
this.props.setForm(this.props.form)
} render(){
//把categoryName解构出来
const {categoryName} = this.props
const { getFieldDecorator } = this.props.form
return(
<Form>
{/*<Item>
<span>所属分类:</span>
{
getFieldDecorator('parentId',{
initialValue:parentId
})(
<Select>
<Option value='1'>一级分类</Option>
</Select>
)
} </Item>*/} <Item>
{/**因为getFiledDecorator接收的标签必须为Form标签,因此span必须拿出来 */}
<span>修改分类名:</span>
{
getFieldDecorator('categoryName',{
//文本框默认值为父组件传过来的对应条目数据的名字
initialValue:categoryName,
rules:[
{required:true,message:'分类名称必须输入'}
]
})( <Input type='text' placeholder='请输入子分类名称' />
)
} </Item> </Form>
)
}
}
export default Form.create()(UpdateCateForm);

效果:同上,但修改一个条目后,再点下g 个条目不会显示之前修改的那个数据

《React后台管理系统实战 :四》产品分类管理页:添加产品分类、修改(更新)产品分类

六、添加产品分类功能实现

6.1添加分类组件完善add-cate-form.jsx

【1】引入父子传值模块

【2】引入父组件的传过来的相关属性

【3】到父组件category/index.jsx下把categorys[],parentId,from对象传过来

【4】取出父组件传过来的categorys,parentId

【5】令inintalValue=parentId(实现在子分类点添加分类时一级分类自动显示对应分类)、把一级分类动态写入(实现自动调取所有一级分类)、

【6】把当前组件的form作为参数运行一下父组件传过来的[接收子组件form对象函数],从而实现父组件也有form对象

【7】回到父组件实现功能

import React,{Component} from 'react'
import {
Form,
Select,
Input
} from 'antd';
import PropTypes from 'prop-types' //【1】引入父子传值模块 const Item=Form.Item
const Option=Select.Option class AddCateForm extends Component{
//【2】引入父组件的相关信息
static propTypes={
categorys:PropTypes.array.isRequired, //父组件的一级分类列表
parentId:PropTypes.string.isRequired, //父组件传过来的当前产品分类的parentId
setForm:PropTypes.func.isRequired,//用来接收父组件传过来的接收子组件form对象的函数
}
//【6】把当前组件的form作为参数运行一下父组件传过来的[接收子组件form对象函数],从而实现父组件也有form对象
componentWillMount(){
this.props.setForm(this.props.form)
} render(){
//【3】到父组件category/index.jsx下把categorys[],parentId,from对象传过来
//【4】取出父组件传过来的categorys,parentId
const {categorys, parentId} = this.props
const { getFieldDecorator } = this.props.form
return(
<Form>
<Item>
<span>所属分类:</span>
{
/*【5】令inintalValue=parentId(实现在子分类点添加分类时一级分类自动显示对应分类)、
把一级分类动态写入(实现自动调取所有一级分类)、【6】回到父组件实现功能*/
getFieldDecorator('parentId',{
initialValue:parentId
})(
<Select>
<Option value='0'>一级分类</Option>
{
categorys.map(c=> <Option value={c._id}>{c.name}</Option>)
}
</Select>
)
} </Item> <Item>
<span>添加子分类:</span>
{
getFieldDecorator('categoryName',{
rules:[
{required:true,message:'分类名称必须输入'}
]
})( <Input type='text' placeholder='请输入子分类名称' />
)
} </Item> </Form>
)
}
}
export default Form.create()(AddCateForm);

6.2 添加分类功能实现:category/index.jsx

【1】把categorys,和parentId、接收子组件from对象的函数、传到子组件add-cate-form.jsx里面

【2】执行添加分类:

1.获取表单数据

2.清除表单数据

3.如果添加成功:

4.隐藏对话框,提示添加成功

5.重新加载产品分类

6.添加失败

import React,{Component} from 'react'
import './index.less'
import {
Button,
Card,
Table,
Icon,
Modal, //引入对话框
message,} from 'antd';
import LinkButton from '../../../components/link-button'
import {reqCategorys,reqAddCategory,reqUpdateCategory} from '../../../api/' //获取api接口请求函数
import AddCateForm from './add-cate-form'; //添加分类表单
import UpdateCateForm from './update-cate-form'; //导入更新分类的表单 export default class Category extends Component{
state={
loading:false, //控制是否显示加载动画
parentId:'0', //初始为0即请求一级产品分类列表
categorys:[], //存放api接口获取的分类列表
parentName:'', //当前子分类的对应父分类名
subCategorys:[], //子分类列表数据
showStatus:0, //添加分类、更新分类显示状态,0:都不显示,1:显示添加,2:显示更新
} //异步请求一级分类列表
getCategorys = async (parentId)=>{
this.setState({loading:true}) //设置加载中动画状态显示
parentId=parentId || this.state.parentId //parentId等于传进来的参数或state里的值
const result=await reqCategorys(parentId) //把0改为从state内动态获取,请求分类数据并赋值给result
if(result.status===0){ //如果返回的status=0,说明返回成功,执行:
console.log(result.data) //测试输出返回的数据
const categorys=result.data //把返回数据赋值给categorys //如果parentId=0则是一级列表,执行:
if(parentId==='0'){
this.setState({
categorys, //(因为名称和state标签名相同,所以用简写)把返回的一级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
}else{//否则是二级列表,执行:
this.setState({
subCategorys:categorys, //把返回的二级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
} }else{
message.error('获取分类列表失败')
}
} //显示一级分类对应二级产品分类函数
showSubCategory=(category)=>{
//先更新状state的parentId为对应新分类的id
this.setState({
parentId:category._id,
parentName:category.name
},()=>{/*setState是异步执行,并不会马上更新完状态,
因此需在其内部写(在状态更新且重新render()后执行)*/
console.log('parentId',this.state.parentId)
this.getCategorys()//获取二级分类列表
}) } //显示一级分类函数,设置id状态即可
showCategorys=()=>{
this.setState({
parentId:'0',
parentName:'',
subCategorys:[],
})
} //初始化表格column列名函数
initColumn=()=>{
//表格列名
this.columns = [
{
title: '分类名',
key: 'name',
dataIndex: 'name',
},
{
title: '操作',
width:'29%',
render: (categoryObj) => (//category代表当前条目对象(名字随意),用于返回需要显示的界面标签
<span>
{/*把当前条目的数据对象传递给updateCate函数 */}
<LinkButton onClick={()=>this.showUpdateCate(categoryObj)}>修改分类</LinkButton>
{/*
添加事件监听点击时调用显示函数
因为如果加括号及参数就会自动执行函数,而不是点击后才执行,所以用一个匿名函数把它包起来
如果parentId=0即是父级列表则显示查看子分类按钮,否则什么也不显示
*/}
{this.state.parentId==='0'?<LinkButton onClick={()=>{this.showSubCategory(categoryObj)}}>查看子分类</LinkButton>:null}
</span>
),
}, ];
} //显示添加分类函数
showAddCate= async (parentId,categoryName)=>{
this.setState({
showStatus:1
})
} //更新分类函数updateCate,接收[2]传来的对应条目数据对象
showUpdateCate=(categoryObj)=>{
//接收参数赋值到当前函数
this.categoryObj=categoryObj
this.setState({
showStatus:2
})
} //取消对话框函数handleCancel
handleCancel=()=>{
//重置所有表单数据,防止上一条数据修改后点取消,下一条使用缓存,点其它条目时展示上一条修改的数据
this.form.resetFields()
this.setState({
showStatus:0
})
} //【2】执行添加分类:
addCate= async ()=>{
//1.获取表单数据
const {parentId,categoryName}=this.form.getFieldsValue()
//2.清除表单数据
this.form.resetFields()
const result = await reqAddCategory(parentId,categoryName)
if(result.status===0){//3.如果添加成功:
//4.隐藏对话框,提示添加成功
this.setState({showStatus:0})
message.success('产品分类添加成功')
//5.重新加载产品分类
this.getCategorys()
}else{
message.error('产品分类添加失败')
}
} //执行修改分类(点对话框的ok按钮执行此函数)
updateCate= async ()=>{
//1.点ok后隐藏对话框
this.setState({showStatus:0})
//2.准备数据
const categoryId=this.categoryObj._id
//从子组件update-cate-form.jsx组件获取要修改的分类名
const categoryName=this.form.getFieldValue('categoryName') //取this的form对象
// console.log('categoryId:',categoryId)
// console.log('categoryName:',categoryName)
//重置所有表单数据,防止使用缓存,造成点其它条目时展示上一条修改的数据
this.form.resetFields()
//3.发送请求更新分类
const result = await reqUpdateCategory({categoryId,categoryName}) if(result.status===0){
message.success('产品分类修改名称成功')
//4.重新显示修改名称后的分类列表
this.getCategorys()
}else{
message.error('产品分类修改名称失败')
}
} // 页面完成加载后运行,用于异步加载等函数存放
componentDidMount(){
this.getCategorys() //获取表格数据源
} // 页面将要加载运行:用于页面渲染前的数据准备
componentWillMount(){
this.initColumn() //准备表格列名相关数据
//this.addCate('5e41578325a557082c18f43b','洗衣机')
} render(){
// 对state里数据解构:
const {categorys,subCategorys, parentId,parentName,loading,showStatus}=this.state
//把4步收到的参数赋值给categoryObj
const categoryOjb = this.categoryObj || {} // 如果还没有,则指定一个空对象 //卡片标题,如果是一及分类显示 一级分类列表,否则显示一级分类+链接+对应的一级分类名
const title= parentId==='0'?'一级分类列表':(
<span>
<LinkButton onClick={this.showCategorys}>一级分类列表</LinkButton> >>
<span>{parentName}</span>
</span>
)
//卡片右侧添加按键:添加监听
const extra=(
<Button type='primary' onClick={this.showAddCate}>
<Icon type='plus'/>
添加
</Button>
) return(
<div className='category'>
{/*卡片样式组件*/}
<Card title={title} extra={extra} >
{/*
表格组件、边框、key为数据源的_id、
数据源、如果parentId为0设置一级分类列表为数据源、否则二级分类为列表源
列名定义、
一页显示数据条数,显示快速跳转
*/}
<Table
bordered
rowKey='_id'
dataSource={parentId==='0'? categorys:subCategorys}
columns={this.columns}
loading={loading}
pagination={{defaultPageSize: 5, showQuickJumper: true}}
/> {/*添加对话框:0:都不显示,1:显示添加分类,2:显示更新分类
添加监听函数:addCate,updateCate,handleCancel
使用<AddCateForm组件 */}
<Modal
title="添加分类"
visible={showStatus===1}
onOk={this.addCate}
onCancel={this.handleCancel}
>
{/**【1】把categorys,和parentId、接收子组件from对象的函数、传到子组件add-cate-form.jsx里面 */}
<AddCateForm
categorys={categorys}
parentId={parentId}
setForm={(form)=>{this.form=form}}
/>
</Modal> {/*
在updateCateForm组件加一个参数categoryName用于传给子组件,
实现更新时显示当前条目的产品分类名称
转到update-cate-form.jsx内接收传过来的参数categoryName
onOk点执行updateCate函数执行分类名修改
*/}
<Modal
title="修改分类"
visible={showStatus===2}
onOk={this.updateCate}
onCancel={this.handleCancel}
>
{/*接收子组件传来的form对象(向子组件传递带参数的函数,子组件调用它,再把from对象通过参数传回来)
子组件把form对象传来之前,将其赋值到this.from里
下接update-cate-form.jsx*/}
<UpdateCateForm
categoryName={categoryOjb.name}
setForm={(form)=>{this.form=form}}
/>
</Modal> </Card>
</div>
)
}
}

效果:http://localhost:3000/category

点【添加分类】成功添加分类,关闭对话框、显示添加成功、重新加载显示分类

《React后台管理系统实战 :四》产品分类管理页:添加产品分类、修改(更新)产品分类

6.3功能完善

问题:

  1. 在2级分类添加其它一级分类、一级分类对应子分类时,点过去看不到其对应分类(原因是添加后没请求2级分类)
  2. 解决,加个判断,在二级分类下添加一级分类/其它子分类,只请求分类列表,但不改变state.parentId即可。

【1】如果新添加的分类就是当前分类下的子分类(当前表单显示的parentId=状态中的parentId):

【2】如果添加的是一级分类(parentId===0),则需获取一级分类,但无需显示

【3】正常要重新设置state里的parentId=0然后再请求一次,但这样会造成跳转到一级分类

因此把parentId直接做为参数传到getCategorys()里,这样就不会跳转显示一级分类,还是在二级分类里了

import React,{Component} from 'react'
import './index.less'
import {
Button,
Card,
Table,
Icon,
Modal, //引入对话框
message,} from 'antd';
import LinkButton from '../../../components/link-button'
import {reqCategorys,reqAddCategory,reqUpdateCategory} from '../../../api/' //获取api接口请求函数
import AddCateForm from './add-cate-form'; //添加分类表单
import UpdateCateForm from './update-cate-form'; //导入更新分类的表单 export default class Category extends Component{
state={
loading:false, //控制是否显示加载动画
parentId:'0', //初始为0即请求一级产品分类列表
categorys:[], //存放api接口获取的分类列表
parentName:'', //当前子分类的对应父分类名
subCategorys:[], //子分类列表数据
showStatus:0, //添加分类、更新分类显示状态,0:都不显示,1:显示添加,2:显示更新
} //异步请求一级分类列表
getCategorys = async (parentId)=>{
this.setState({loading:true}) //设置加载中动画状态显示
parentId=parentId || this.state.parentId //parentId等于传进来的参数或state里的值
const result=await reqCategorys(parentId) //把0改为从state内动态获取,请求分类数据并赋值给result
if(result.status===0){ //如果返回的status=0,说明返回成功,执行:
console.log(result.data) //测试输出返回的数据
const categorys=result.data //把返回数据赋值给categorys //如果parentId=0则是一级列表,执行:
if(parentId==='0'){
this.setState({
categorys, //(因为名称和state标签名相同,所以用简写)把返回的一级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
}else{//否则是二级列表,执行:
this.setState({
subCategorys:categorys, //把返回的二级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
} }else{
message.error('获取分类列表失败')
}
} //显示一级分类对应二级产品分类函数
showSubCategory=(category)=>{
//先更新状state的parentId为对应新分类的id
this.setState({
parentId:category._id,
parentName:category.name
},()=>{/*setState是异步执行,并不会马上更新完状态,
因此需在其内部写(在状态更新且重新render()后执行)*/
console.log('parentId',this.state.parentId)
this.getCategorys()//获取二级分类列表
}) } //显示一级分类函数,设置id状态即可
showCategorys=()=>{
this.setState({
parentId:'0',
parentName:'',
subCategorys:[],
})
} //初始化表格column列名函数
initColumn=()=>{
//表格列名
this.columns = [
{
title: '分类名',
key: 'name',
dataIndex: 'name',
},
{
title: '操作',
width:'29%',
render: (categoryObj) => (//category代表当前条目对象(名字随意),用于返回需要显示的界面标签
<span>
{/*把当前条目的数据对象传递给updateCate函数 */}
<LinkButton onClick={()=>this.showUpdateCate(categoryObj)}>修改分类</LinkButton>
{/*
添加事件监听点击时调用显示函数
因为如果加括号及参数就会自动执行函数,而不是点击后才执行,所以用一个匿名函数把它包起来
如果parentId=0即是父级列表则显示查看子分类按钮,否则什么也不显示
*/}
{this.state.parentId==='0'?<LinkButton onClick={()=>{this.showSubCategory(categoryObj)}}>查看子分类</LinkButton>:null}
</span>
),
}, ];
} //显示添加分类函数
showAddCate= async (parentId,categoryName)=>{
this.setState({
showStatus:1
})
} //更新分类函数updateCate,接收[2]传来的对应条目数据对象
showUpdateCate=(categoryObj)=>{
//接收参数赋值到当前函数
this.categoryObj=categoryObj
this.setState({
showStatus:2
})
} //取消对话框函数handleCancel
handleCancel=()=>{
//重置所有表单数据,防止上一条数据修改后点取消,下一条使用缓存,点其它条目时展示上一条修改的数据
this.form.resetFields()
this.setState({
showStatus:0
})
} //执行添加分类:
addCate= async ()=>{
//1.获取表单数据
const {parentId,categoryName}=this.form.getFieldsValue()
//2.清除表单数据
this.form.resetFields()
const result = await reqAddCategory(parentId,categoryName)
if(result.status===0){//3.如果添加成功:
// 【1】如果新添加的分类就是当前分类下的子分类(当前表单显示的parentId=状态中的parentId):
if(parentId===this.state.parentId){
//隐藏对话框,提示添加成功
this.setState({showStatus:0})
message.success('产品分类添加成功')
//重新加载请求并展示添加之后的产品分类
this.getCategorys()
}else if(parentId==='0'){//【2】如果添加的是一级分类(parentId===0),则需获取一级分类,但无需显示
//【3】正常要重新设置state里的parentId=0然后再请求一次,但这样会造成跳转到一级分类
//因此把parentId直接做为参数传到getCategorys()里,这样就不会跳转显示一级分类,还是在二级分类里了
this.getCategorys('0')
//隐藏对话框,提示添加成功
this.setState({showStatus:0})
message.success('产品分类添加成功')
}else{//否则(添加其它分类下的子分类)
message.error('不能添加其它分类的子分类!')
} }else{//6.添加失败:
message.error('产品分类添加失败')
}
} //执行修改分类(点对话框的ok按钮执行此函数)
updateCate= async ()=>{
//1.点ok后隐藏对话框
this.setState({showStatus:0})
//2.准备数据
const categoryId=this.categoryObj._id
//从子组件update-cate-form.jsx组件获取要修改的分类名
const categoryName=this.form.getFieldValue('categoryName') //取this的form对象
// console.log('categoryId:',categoryId)
// console.log('categoryName:',categoryName)
//重置所有表单数据,防止使用缓存,造成点其它条目时展示上一条修改的数据
this.form.resetFields()
//3.发送请求更新分类
const result = await reqUpdateCategory({categoryId,categoryName}) if(result.status===0){
message.success('产品分类修改名称成功')
//4.重新显示修改名称后的分类列表
this.getCategorys()
}else{
message.error('产品分类修改名称失败')
}
} // 页面完成加载后运行,用于异步加载等函数存放
componentDidMount(){
this.getCategorys() //获取表格数据源
} // 页面将要加载运行:用于页面渲染前的数据准备
componentWillMount(){
this.initColumn() //准备表格列名相关数据
//this.addCate('5e41578325a557082c18f43b','洗衣机')
} render(){
// 对state里数据解构:
const {categorys,subCategorys, parentId,parentName,loading,showStatus}=this.state
//把4步收到的参数赋值给categoryObj
const categoryOjb = this.categoryObj || {} // 如果还没有,则指定一个空对象 //卡片标题,如果是一及分类显示 一级分类列表,否则显示一级分类+链接+对应的一级分类名
const title= parentId==='0'?'一级分类列表':(
<span>
<LinkButton onClick={this.showCategorys}>一级分类列表</LinkButton> >>
<span>{parentName}</span>
</span>
)
//卡片右侧添加按键:添加监听
const extra=(
<Button type='primary' onClick={this.showAddCate}>
<Icon type='plus'/>
添加
</Button>
) return(
<div className='category'>
{/*卡片样式组件*/}
<Card title={title} extra={extra} >
{/*
表格组件、边框、key为数据源的_id、
数据源、如果parentId为0设置一级分类列表为数据源、否则二级分类为列表源
列名定义、
一页显示数据条数,显示快速跳转
*/}
<Table
bordered
rowKey='_id'
dataSource={parentId==='0'? categorys:subCategorys}
columns={this.columns}
loading={loading}
pagination={{defaultPageSize: 5, showQuickJumper: true}}
/> {/*添加对话框:0:都不显示,1:显示添加分类,2:显示更新分类
添加监听函数:addCate,updateCate,handleCancel
使用<AddCateForm组件 */}
<Modal
title="添加分类"
visible={showStatus===1}
onOk={this.addCate}
onCancel={this.handleCancel}
>
{/**把categorys,和parentId、接收子组件from对象的函数、传到子组件add-cate-form.jsx里面 */}
<AddCateForm
categorys={categorys}
parentId={parentId}
setForm={(form)=>{this.form=form}}
/>
</Modal> {/*
在updateCateForm组件加一个参数categoryName用于传给子组件,
实现更新时显示当前条目的产品分类名称
转到update-cate-form.jsx内接收传过来的参数categoryName
onOk点执行updateCate函数执行分类名修改
*/}
<Modal
title="修改分类"
visible={showStatus===2}
onOk={this.updateCate}
onCancel={this.handleCancel}
>
{/*接收子组件传来的form对象(向子组件传递带参数的函数,子组件调用它,再把from对象通过参数传回来)
子组件把form对象传来之前,将其赋值到this.from里
下接update-cate-form.jsx*/}
<UpdateCateForm
categoryName={categoryOjb.name}
setForm={(form)=>{this.form=form}}
/>
</Modal> </Card>
</div>
)
}
}

6.4添加表单验证:更新表单验证

antd表单及规则编写

【1】在字段装饰器加入规则【2】到父组件内写验证

<Item>
<span>添加子分类:</span>
{
getFieldDecorator('categoryName',{
//【1】在字段装饰器加入规则【2】到父组件内写验证
rules:[
{required:true,message:'分类名称必须输入'}
]
})( <Input type='text' placeholder='请输入子分类名称' />
)
}
</Item>

表单验证函数

//antd的表单验证函数结构
this.form.validateFields((err,values)=>{
//如果没有错误
if(!err){
//写点ok提交数据要执行的代码
}
})

表单验证完整函数

//执行添加分类:
addCate= ()=>{
//【1】antd表单验证函数
this.form.validateFields(async (err,values)=>{
if(!err){//【2】把所有提交数据要执行的代码都放入表单验证无错误之后
//1.获取表单数据
// const {parentId,categoryName}=this.form.getFieldsValue()
//【3】注释旧上一行,改成从values里解构需要的数据
const {parentId,categoryName}=values
//2.清除表单数据
this.form.resetFields()
const result = await reqAddCategory(parentId,categoryName)
if(result.status===0){//3.如果添加成功:
// 如果新添加的分类就是当前分类下的子分类(当前表单显示的parentId=状态中的parentId):
if(parentId===this.state.parentId){
//隐藏对话框,提示添加成功
this.setState({showStatus:0})
message.success('产品分类添加成功')
//重新加载请求并展示添加之后的产品分类
this.getCategorys()
}else if(parentId==='0'){//如果添加的是一级分类(parentId===0),则需获取一级分类,但无需显示
//正常要重新设置state里的parentId=0然后再请求一次,但这样会造成跳转到一级分类
//因此把parentId直接做为参数传到getCategorys()里,这样就不会跳转显示一级分类,还是在二级分类里了
this.getCategorys('0')
//隐藏对话框,提示添加成功
this.setState({showStatus:0})
message.success('产品分类添加成功')
}else{
message.error('不能添加其它分类的子分类!')
} }else{//6.添加失败:
message.error('产品分类添加失败')
}
}
})
}

6.5更新产品分类的表单验证

表单部分update-cate-form.jsx

<Item>
{/**因为getFiledDecorator接收的标签必须为Form标签,因此span必须拿出来 */}
<span>修改分类名:</span>
{
getFieldDecorator('categoryName',{
//文本框默认值为父组件传过来的对应条目数据的名字
initialValue:categoryName,
//【1】加入规则【2】到父组件内写验证
rules:[
{required:true,message:'分类名称必须输入'}
]
})( <Input type='text' placeholder='请输入子分类名称' />
)
} </Item>

验证部分category/index.jsx:

//执行修改分类(点对话框的ok按钮执行此函数)
updateCate= ()=>{
//【1】表单的验证函数
this.form.validateFields(async(err,values)=>{
//【2】如果没错
if(!err){
//1.点ok后隐藏对话框
this.setState({showStatus:0})
//2.准备数据
const categoryId=this.categoryObj._id
//从子组件update-cate-form.jsx组件获取要修改的分类名
//const categoryName=this.form.getFieldValue('categoryName') //取this的form对象
//【3】注释上一行,改成如下从values解构
const {categoryName}=values
// console.log('categoryId:',categoryId)
// console.log('categoryName:',categoryName)
//重置所有表单数据,防止使用缓存,造成点其它条目时展示上一条修改的数据
this.form.resetFields()
//3.发送请求更新分类
const result = await reqUpdateCategory({categoryId,categoryName}) if(result.status===0){
message.success('产品分类修改名称成功')
//4.重新显示修改名称后的分类列表
this.getCategorys()
}else{
message.error('产品分类修改名称失败')
}
}
}) }

6.4-6.5完整代码

index.jsx

import React,{Component} from 'react'
import './index.less'
import {
Button,
Card,
Table,
Icon,
Modal, //引入对话框
message,} from 'antd';
import LinkButton from '../../../components/link-button'
import {reqCategorys,reqAddCategory,reqUpdateCategory} from '../../../api/' //获取api接口请求函数
import AddCateForm from './add-cate-form'; //添加分类表单
import UpdateCateForm from './update-cate-form'; //导入更新分类的表单 export default class Category extends Component{
state={
loading:false, //控制是否显示加载动画
parentId:'0', //初始为0即请求一级产品分类列表
categorys:[], //存放api接口获取的分类列表
parentName:'', //当前子分类的对应父分类名
subCategorys:[], //子分类列表数据
showStatus:0, //添加分类、更新分类显示状态,0:都不显示,1:显示添加,2:显示更新
} //异步请求一级分类列表
getCategorys = async (parentId)=>{
this.setState({loading:true}) //设置加载中动画状态显示
parentId=parentId || this.state.parentId //parentId等于传进来的参数或state里的值
const result=await reqCategorys(parentId) //把0改为从state内动态获取,请求分类数据并赋值给result
if(result.status===0){ //如果返回的status=0,说明返回成功,执行:
console.log(result.data) //测试输出返回的数据
const categorys=result.data //把返回数据赋值给categorys //如果parentId=0则是一级列表,执行:
if(parentId==='0'){
this.setState({
categorys, //(因为名称和state标签名相同,所以用简写)把返回的一级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
}else{//否则是二级列表,执行:
this.setState({
subCategorys:categorys, //把返回的二级产品分类数据,赋值给state里
loading:false, //数据加载完成,取消loading动画显示
})
} }else{
message.error('获取分类列表失败')
}
} //显示一级分类对应二级产品分类函数
showSubCategory=(category)=>{
//先更新状state的parentId为对应新分类的id
this.setState({
parentId:category._id,
parentName:category.name
},()=>{/*setState是异步执行,并不会马上更新完状态,
因此需在其内部写(在状态更新且重新render()后执行)*/
console.log('parentId',this.state.parentId)
this.getCategorys()//获取二级分类列表
}) } //显示一级分类函数,设置id状态即可
showCategorys=()=>{
this.setState({
parentId:'0',
parentName:'',
subCategorys:[],
})
} //初始化表格column列名函数
initColumn=()=>{
//表格列名
this.columns = [
{
title: '分类名',
key: 'name',
dataIndex: 'name',
},
{
title: '操作',
width:'29%',
render: (categoryObj) => (//category代表当前条目对象(名字随意),用于返回需要显示的界面标签
<span>
{/*把当前条目的数据对象传递给updateCate函数 */}
<LinkButton onClick={()=>this.showUpdateCate(categoryObj)}>修改分类</LinkButton>
{/*
添加事件监听点击时调用显示函数
因为如果加括号及参数就会自动执行函数,而不是点击后才执行,所以用一个匿名函数把它包起来
如果parentId=0即是父级列表则显示查看子分类按钮,否则什么也不显示
*/}
{this.state.parentId==='0'?<LinkButton onClick={()=>{this.showSubCategory(categoryObj)}}>查看子分类</LinkButton>:null}
</span>
),
}, ];
} //显示添加分类函数
showAddCate= async (parentId,categoryName)=>{
this.setState({
showStatus:1
})
} //更新分类函数updateCate,接收[2]传来的对应条目数据对象
showUpdateCate=(categoryObj)=>{
//接收参数赋值到当前函数
this.categoryObj=categoryObj
this.setState({
showStatus:2
})
} //取消对话框函数handleCancel
handleCancel=()=>{
//重置所有表单数据,防止上一条数据修改后点取消,下一条使用缓存,点其它条目时展示上一条修改的数据
this.form.resetFields()
this.setState({
showStatus:0
})
} //执行添加分类:
addCate= ()=>{
//【1】antd表单验证函数
this.form.validateFields(async (err,values)=>{
if(!err){//【2】把所有提交数据要执行的代码都放入表单验证无错误之后
//1.获取表单数据
// const {parentId,categoryName}=this.form.getFieldsValue()
//【3】注释旧上一行,改成从values里解构需要的数据
const {parentId,categoryName}=values
//2.清除表单数据
this.form.resetFields()
const result = await reqAddCategory(parentId,categoryName)
if(result.status===0){//3.如果添加成功:
// 如果新添加的分类就是当前分类下的子分类(当前表单显示的parentId=状态中的parentId):
if(parentId===this.state.parentId){
//隐藏对话框,提示添加成功
this.setState({showStatus:0})
message.success('产品分类添加成功')
//重新加载请求并展示添加之后的产品分类
this.getCategorys()
}else if(parentId==='0'){//如果添加的是一级分类(parentId===0),则需获取一级分类,但无需显示
//正常要重新设置state里的parentId=0然后再请求一次,但这样会造成跳转到一级分类
//因此把parentId直接做为参数传到getCategorys()里,这样就不会跳转显示一级分类,还是在二级分类里了
this.getCategorys('0')
//隐藏对话框,提示添加成功
this.setState({showStatus:0})
message.success('产品分类添加成功')
}else{
message.error('不能添加其它分类的子分类!')
} }else{//6.添加失败:
message.error('产品分类添加失败')
}
}
}) } //执行修改分类(点对话框的ok按钮执行此函数)
updateCate= ()=>{
//【1】表单的验证函数
this.form.validateFields(async(err,values)=>{
//【2】如果没错
if(!err){
//1.点ok后隐藏对话框
this.setState({showStatus:0})
//2.准备数据
const categoryId=this.categoryObj._id
//从子组件update-cate-form.jsx组件获取要修改的分类名
//const categoryName=this.form.getFieldValue('categoryName') //取this的form对象
//【3】注释上一行,改成如下从values解构
const {categoryName}=values
// console.log('categoryId:',categoryId)
// console.log('categoryName:',categoryName)
//重置所有表单数据,防止使用缓存,造成点其它条目时展示上一条修改的数据
this.form.resetFields()
//3.发送请求更新分类
const result = await reqUpdateCategory({categoryId,categoryName}) if(result.status===0){
message.success('产品分类修改名称成功')
//4.重新显示修改名称后的分类列表
this.getCategorys()
}else{
message.error('产品分类修改名称失败')
}
}
}) } // 页面完成加载后运行,用于异步加载等函数存放
componentDidMount(){
this.getCategorys() //获取表格数据源
} // 页面将要加载运行:用于页面渲染前的数据准备
componentWillMount(){
this.initColumn() //准备表格列名相关数据
//this.addCate('5e41578325a557082c18f43b','洗衣机')
} render(){
// 对state里数据解构:
const {categorys,subCategorys, parentId,parentName,loading,showStatus}=this.state
//把4步收到的参数赋值给categoryObj
const categoryOjb = this.categoryObj || {} // 如果还没有,则指定一个空对象 //卡片标题,如果是一及分类显示 一级分类列表,否则显示一级分类+链接+对应的一级分类名
const title= parentId==='0'?'一级分类列表':(
<span>
<LinkButton onClick={this.showCategorys}>一级分类列表</LinkButton> >>
<span>{parentName}</span>
</span>
)
//卡片右侧添加按键:添加监听
const extra=(
<Button type='primary' onClick={this.showAddCate}>
<Icon type='plus'/>
添加
</Button>
) return(
<div className='category'>
{/*卡片样式组件*/}
<Card title={title} extra={extra} >
{/*
表格组件、边框、key为数据源的_id、
数据源、如果parentId为0设置一级分类列表为数据源、否则二级分类为列表源
列名定义、
一页显示数据条数,显示快速跳转
*/}
<Table
bordered
rowKey='_id'
dataSource={parentId==='0'? categorys:subCategorys}
columns={this.columns}
loading={loading}
pagination={{defaultPageSize: 5, showQuickJumper: true}}
/> {/*添加对话框:0:都不显示,1:显示添加分类,2:显示更新分类
添加监听函数:addCate,updateCate,handleCancel
使用<AddCateForm组件 */}
<Modal
title="添加分类"
visible={showStatus===1}
onOk={this.addCate}
onCancel={this.handleCancel}
>
{/**把categorys,和parentId、接收子组件from对象的函数、传到子组件add-cate-form.jsx里面 */}
<AddCateForm
categorys={categorys}
parentId={parentId}
setForm={(form)=>{this.form=form}}
/>
</Modal> {/*
在updateCateForm组件加一个参数categoryName用于传给子组件,
实现更新时显示当前条目的产品分类名称
转到update-cate-form.jsx内接收传过来的参数categoryName
onOk点执行updateCate函数执行分类名修改
*/}
<Modal
title="修改分类"
visible={showStatus===2}
onOk={this.updateCate}
onCancel={this.handleCancel}
>
{/*接收子组件传来的form对象(向子组件传递带参数的函数,子组件调用它,再把from对象通过参数传回来)
子组件把form对象传来之前,将其赋值到this.from里
下接update-cate-form.jsx*/}
<UpdateCateForm
categoryName={categoryOjb.name}
setForm={(form)=>{this.form=form}}
/>
</Modal> </Card>
</div>
)
}
}

update-cate-fomr.jsx

import React,{Component} from 'react'
import {
Form,
Select,
Input
} from 'antd'
import PropTypes from 'prop-types' //接收父组件传值组件 const Item=Form.Item
const Option=Select.Option class UpdateCateForm extends Component{
//把从父组件接收过来的属性参数接收过来
static propTypes={
categoryName:PropTypes.string.isRequired,
//设置setForm类型为函数且必须
setForm:PropTypes.func.isRequired,
} //在此组件渲染之前调用一次setForm函数,把form传到父组件去
componentWillMount(){
//将form对象通过setForm函数传给父组件
this.props.setForm(this.props.form)
} render(){
//把categoryName解构出来
const {categoryName} = this.props
const { getFieldDecorator } = this.props.form
return(
<Form>
{/*<Item>
<span>所属分类:</span>
{
getFieldDecorator('parentId',{
initialValue:parentId
})(
<Select>
<Option value='1'>一级分类</Option>
</Select>
)
} </Item>*/} <Item>
{/**因为getFiledDecorator接收的标签必须为Form标签,因此span必须拿出来 */}
<span>修改分类名:</span>
{
getFieldDecorator('categoryName',{
//文本框默认值为父组件传过来的对应条目数据的名字
initialValue:categoryName,
//【1】加入规则【2】到父组件内写验证
rules:[
{required:true,message:'分类名称必须输入'}
]
})( <Input type='text' placeholder='请输入子分类名称' />
)
} </Item> </Form>
)
}
}
export default Form.create()(UpdateCateForm);

add-cate-form.jsx

import React,{Component} from 'react'
import {
Form,
Select,
Input
} from 'antd'
import PropTypes from 'prop-types' //接收父组件传值组件 const Item=Form.Item
const Option=Select.Option class UpdateCateForm extends Component{
//把从父组件接收过来的属性参数接收过来
static propTypes={
categoryName:PropTypes.string.isRequired,
//设置setForm类型为函数且必须
setForm:PropTypes.func.isRequired,
} //在此组件渲染之前调用一次setForm函数,把form传到父组件去
componentWillMount(){
//将form对象通过setForm函数传给父组件
this.props.setForm(this.props.form)
} render(){
//把categoryName解构出来
const {categoryName} = this.props
const { getFieldDecorator } = this.props.form
return(
<Form>
{/*<Item>
<span>所属分类:</span>
{
getFieldDecorator('parentId',{
initialValue:parentId
})(
<Select>
<Option value='1'>一级分类</Option>
</Select>
)
} </Item>*/} <Item>
{/**因为getFiledDecorator接收的标签必须为Form标签,因此span必须拿出来 */}
<span>修改分类名:</span>
{
getFieldDecorator('categoryName',{
//文本框默认值为父组件传过来的对应条目数据的名字
initialValue:categoryName,
//【1】加入规则【2】到父组件内写验证
rules:[
{required:true,message:'分类名称必须输入'}
]
})( <Input type='text' placeholder='请输入子分类名称' />
)
} </Item> </Form>
)
}
}
export default Form.create()(UpdateCateForm);

效果:http://localhost:3000/category

《React后台管理系统实战 :四》产品分类管理页:添加产品分类、修改(更新)产品分类

《React后台管理系统实战 :四》产品分类管理页:添加产品分类、修改(更新)产品分类

上一篇:将img设置成div背景图片


下一篇:Mac 下 docker安装