后台的API接口在此文件,根据后台定义可知请求路径
后面自己验证一下这三个参数,不知道text和record的区别。
发现text和record完全相同,
console.log(text === record)
render: (text , record, index) => (
<span>
<button onClick={() => this.print(text, record, index)}>查看</button>
结果:前提是该列没有设置dataIndex,所以找不到对应的对象属性,text参数直接是整个对象
如果该列设置了dataIndex: ‘name’,则text就是对象的name属性值。而record是整个对象
console.log(text, record)
设置Table组件的rowKey=’_id’属性
注意,在 label 对应的 Form.Item 上不要在指定 name 属性,这个 Item 只作为布局作用。
复杂的控件(antd)
Category路由组件
怎么完成一个复杂多功能的组件,按常用的步骤和需求。
静态页面
知识概要:
dataSource数据直接是请求得到的数组,数组元素以对象形式展示类别信息。
columns会根据dataIndex决定对象哪些属性展示到table中。
之前的对话框Modal是以按钮触发函数,函数内部的使用 confirm() 可以快捷地弹出确认框。这里使用Modal组件标签,其中由属性visible来决定是否显示
<Card title={title} extra={extra}>
<Table bordered
rowKey='_id'
dataSource={parent === '0' ? categorys : subCategorys}
columns={this.columns}
loading={loading}
pagination={{ pageSize: 5, showQuickJumper: true, showSizeChanger: true }}
/>
<Modal title="添加分类" visible={showStatus === 1}>
<AddForm />
</Modal>
<Modal title="修改分类" visible={showStatus === 2}>
<UpdateForm />
</Modal>
</Card>
columns
this.columns = [
{
title: '分类名称',
dataIndex: 'name'
},
{
title: '操作',
width: 300, //该列的宽度
render: (category) => (
<span>
<LinkButton onClick={() => this.showUpdate(category)}>修改分类</LinkButton>
{this.state.parentId === '0' ? <LinkButton onClick={() => this.showSubCates(category)}>
查看子分类</LinkButton> : null}
</span>
)
}];
定义控制变量static
state = {
categorys: [], // 一级分类列表
subCategorys: [], // 二级分类列表
parentId: '0', // 父分类的ID 用来查询二级分类
parentName: '', // 父分类的名称
loading: false, // 标识Table是否加载中
showStatus: 0, // 是否显示Modal,0:不显示 1:添加框 2:更新框
}
获取数据
1.根据 parentId 异步获取分类列表显示
getCategorys = async (parentId) => {
const result = await reqCategorys(parentId)
if (result.status === 0) {
const categorys = result.data
if (parentId === '0') {
this.setState({categorys})
} else {
this.setState({subCategorys: categorys})
}
} else {
message.error('获取列表失败')
}
}
2.显示指定分类的子分类列表
showSubCates = (category) => {
this.setState({ parentId: category._id, parentName: category.name }, () => {
// 在状态更新之后执行, 在回调函数中能得到最新的状态数据
this.getCategorys()
})
}
3.由展示二级列表转为一级列表
transToCates = () => {
// 因为类中还存储着一级列表的数据
this.setState({
parentId: '0',
parentName: '',
subCategorys: [],
showStatus: 0,
})
}
4.显示修改的对话框——(输入框要显示原来的值)
showUpdate = (category) => {
// 输入框要显示原来的值, 保存在class里面
this.category = category
this.setState({ showStatus: 2 })
}
<LinkButton onClick={() => this.showUpdate(category)}>修改分类</LinkButton>
5.传给子组件当前category信息,子组件才知道修改哪个分类对象。
得到子组件里面的Form信息,这样才能根据表单信息发生更新请求。
<Modal title="修改分类" visible={showStatus === 2}
onOk={this.reqUpdateCategory}
onCancel={() => {
this.setState({ showStatus: 0 })
// this.form.current.resetFields()
}}
destroyOnClose={true}
>
<UpdateForm
categoryName={category.name}
setForm={form => this.form = form}
/>
</Modal>
6.发送添加分类的请求 (修改分类请求类似)
addCategory = () => {
this.form.current.validateFields().then(async (values) => {
this.setState({ showStatus: 0 })
const { parentId, categoryName } = values
const result = await reqAddCategory(categoryName, parentId)
if (result.status === 0) {
//添加的分类属于当前页面展示的分类
if (parentId === this.state.parentId) {
this.getCategorys()
} else if (parentId === '0') {
// 在二级分类列表下添加一级分类, 因为由二级分类返回一级分类不用查询数据库
this.getCategorys('0')
}
}
}).catch((err) => {
message.info('请输入分类名称')
})
}
知识点一:
情景:通过State对象的属性来控制查询的父级 / 子级 分类列表。但setState函数此时为异步更新。后果:调用查询分类列表的函数时,state.parentId还是为0,(表示查询父级列表)
而render()时,state.paretId就改变(表示显示子级列表)
将 setState() 视为请求而不是立即更新组件的命令。为了更好的感知性能,React 会延迟调用它,然后通过一次传递更新多个组件。React 并不会保证 state 的变更会立即生效。
setState() 并不总是立即更新组件。它会批量推迟更新。这使得在调用 setState() 后立即读取 this.state 成为了隐患。为了消除隐患,请使用 componentDidUpdate 或者 setState 的回调函数(setState(updater, callback)),这两种方式都可以保证在应用更新后触发。如需基于之前的 state 来设置当前的 state,请阅读下述关于参数 updater 的内容。
视频讲到的情景:如果你不修改Form的输入框,每次点击不同的分类列表对应的修改分类按钮,Form都会初始化不同的相应值。如果修改了Form的输入框,点击Modal组件的确认和取消按钮,下次点击修改分类按钮,Form会保持上一次修改的Input表单的值。
方法一 (不行):
点击确认或者取消按钮的回调事件里,都清除表单数据
this.form.current.resetFields()
第一次点击名称A的修改分类时,会正确读取;再次点击名称B的修改分类时,依然得到的是上一次点击的名称A的缓存,当再次点击名称B时——即滞后一次
方法二:
<Modal destroyOnClose={true} >
关闭时销毁 Modal 里的子元素
知识点三:
- 如何向回调函数传递参数
点击按钮就会执行箭头函数,箭头函数再去执行带实参的回调函数
onClick={() => this.showSubCates(category)
- 子组件如何向父组件传递参数
父组件给子组件一个函数,由子组件执行传递实参,但赋值的是父组件的this
<UpdateForm setForm={form => this.form = form} />