一、静态页面
目录结构
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>
)
}
}
二、动态:产品分类数据请求
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
四、添加分类、更新分类基础布局
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
五、修改产品分类功能实现
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);
效果:
3.执行修改产品分类
- 知识点,子向父组件传值
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 个条目不会显示之前修改的那个数据
六、添加产品分类功能实现
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
点【添加分类】成功添加分类,关闭对话框、显示添加成功、重新加载显示分类
6.3功能完善
问题:
- 在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