
Company News
Socket Joins New OpenJS Program to Fund Node.js Security Work
Socket is joining the OpenJS Security Stewardship Program to fund Node.js vulnerability research, maintainer remediation, and security releases.
igroot-table-page
Advanced tools
适用于绝大部分搜索列表页面,例如
首先默认大家都有用sl 安装过最新的前端模板,并且也懂得怎么配置页面路由,其他的就不多说,主要来讲讲这个场景类的高阶组件的用法,那我们先看一下项目目录
简化一下,只保留我们需要的那部分
.
├── apis
│ ├── customer #api目录
│ │ ├── createFusion.js
│ │ ├── customerDomainInfo.js
│ │ ├── customerDomainList.js
│ │ ├── customerDomainSolutionViewList.js
│ │ ├── customerList.js
│ │ ├── deleteFusion.js
│ │ ├── fusionPage.js
│ │ ├── querySynTime.js
│ │ ├── realTimeDomain.js
│ │ ├── synTime.js
│ │ └── updateFusion.js
│ └── supplier
│ ├── createSupplier.js
│ ├── deleteSupplier.js
│ ├── supplierList.js
│ ├── supplierPage.js
│ └── updateSupplier.js
├── components #组件存放的位置
│ └── TablePage
│ ├── README.md
│ └── index.jsx # 列表高组件
├── pages
│ └── home
│ ├── App.jsx
│ ├── RelationConfigManage # 使用高阶组件的页面目录
│ │ ├── List
│ │ │ ├── index.jsx # 表格组件
│ │ ├── Search.jsx # 搜索栏组件
│ │ └── index.jsx # 入口文件(容器组件)
│ ├── SupplierManage
│ │ ├── List
│ │ │ ├── SupplierEditModal.jsx
│ │ │ └── index.jsx
│ │ ├── Search.jsx
│ │ └── index.jsx
│ ├── index.html
│ ├── index.jsx
│ ├── index.scss
│ └── routerConfig.js
通过sl生成的最新模板后,找到pages下面的index,然后创建一个大写开头的文件夹,内部结构如下
│ ├── SupplierManage # 使用高阶组件的页面目录
│ │ ├── List
│ │ │ ├── index.jsx # 表格组件
│ │ ├── Search.jsx # 搜索栏组件
│ │ └── index.jsx # 入口文件(容器组件)
现在创建完相对应的文件之后接着
直接贴代码
主要看这两部分代码
import React, { Component } from 'react'
import { Row, Col, Input } from 'igroot'
const formItemLayout = {
labelCol: { span: 6 },
wrapperCol: { span: 18 },
}
class Search extends Component {
render() {
// 组件接收到父级传入的 form 和Item 属性
const { getFieldDecorator } = this.props.form
const { Item } = this.props
return <Row>
<Col span={6}>
<Item
{...formItemLayout}
label="厂商"
>
{
getFieldDecorator('supplier_name')(
<Input />
)
}
</Item>
</Col>
<Col span={18}>
// 组件接收到父级传入的 renderButtons 方法
{this.props.renderButtons()}
</Col>
</Row>
}
}
export { Search }
前面提到了思路是基于组件赋能,我们看得部分都是由父级组件提供给我们的方法和属性,我们只管调用就是了。其他部分的代码属于UI层面的,这一部分我们不管,每个业务都不一样。
先贴代码
然后还是看一下props部分
import React, { Component } from 'react'
import { Row, Col, Table, Button, message, Popconfirm } from 'igroot'
import { deleteSupplier } from '@/apis/supplier/deleteSupplier'
export class List extends Component {
state = {
expandKeys: [],
columns: [
{
title: '厂商',
dataIndex: 'supplier_name',
width: 150,
},
{
title: '厂商英文名',
dataIndex: 'supplier_ename',
width: 150,
},
{
title: '默认cname后缀',
dataIndex: 'supplier_cname_suffix',
width: 200,
},
{
title: '创建时间',
dataIndex: 'created_at',
width: 200,
},
{
title: '备注',
dataIndex: 'remark',
width: 200
},
{
title: '操作',
dataIndex: 'handel',
width: 80,
render: (text, row) => <div style={{ textAlign: 'center' }}>
<a style={{ marginRight: 8 }} onClick={() => this.edit(row)}>编辑</a>
<Popconfirm title="确定删除?" onConfirm={() => this.del(row.id)}>
<a>删除</a>
</Popconfirm>
</div>
}
]
}
del = id => {
if (this.delLoading) {
return false
}
const loading = message.loading('删除中,请稍后....')
deleteSupplier({ id: [id] }).then(res => {
loading()
this.delLoading = false
if (res.data.deleteSupplier.result) {
message.success('删除成功')
// 组件接收到了父级的handleReload的方法
this.props.handleReload()
}
})
}
render() {
const { columns } = this.state
return (
<Row>
<Col span={24} style={{ textAlign: 'right' }}>
<Button type="primary" onClick={() => this.Create()} style={{ marginRight: 8 }}>
新增
</Button>
</Col>
<Col span={24} style={{ marginTop: 8 }}>
<Table
columns={columns}
// 组件接收到了父级的tableProps 的属性
{...this.props.tableProps}
/>
</Col>
</Row>
)
}
}
表格组件也接收到了父级的方法和属性,你只需要知道具体提供了哪些,然后你需要在哪里用就好了。剩下的代码是UI层面和表格自己的一些业务逻辑,这部分差异性也比较大。
贴代码
import React, { PureComponent } from 'react'
import { Card } from 'igroot'
import { Search } from './Search'
import { List } from './List/'
import TablePage from '@/components/TablePage/'
import { querySupplierPage } from '@/apis/supplier/supplierPage'
@TablePage({
queryData: (params, pageInfo, state, cb) =>
querySupplierPage({ ...params, ...pageInfo }).then(res => {
if (res) {
cb(
{
dataSource: res.data.supplierPage.supplier_list,
total: res.data.supplierPage.pagination.total
}
)
} else {
cb(false)
}
})
})
export class SupplierManage extends PureComponent {
render() {
return (
<Card bodyStyle={{ padding: 10 }} >
<Search />
<List />
</Card>
)
}
}
这部分代码分为两个步骤,第一创建一个容器组件包装上面提到的两个组件 一个是Search 和List ,在这里我是使用Card组件,你也可以用div或者其他。
务必Search在上,List在下。
务必Search在上,List在下。
务必Search在上,List在下。
export class SupplierManage extends PureComponent {
render() {
return (
<Card bodyStyle={{ padding: 10 }} >
<Search />
<List />
</Card>
)
}
}
创建完容器组件之后最后才会请出我们的高阶组件。
在这边做个简单介绍,其实所谓高阶组件就是一个函数,函数的入参是一些业务相关的配置和一个组件,函数根据对应的配置改造传入的组件赋予我们抽象出来的业务逻辑,返回一个新的组件。
下面是装饰器写法,
我传入的是一个对象里面有一个叫queryData的函数,这个函数用来请求列表数据,里面我只简单的写了一下入参的格式和请求成功后应该返回什么。之后这个函数应该在什么时候调用就不用我们操心了。
然后再传入对应的组件,完事。
@TablePage({
queryData: (params, pageInfo, state, cb) =>
querySupplierPage({ ...params, ...pageInfo }).then(res => {
if (res) {
cb(
{
dataSource: res.data.supplierPage.supplier_list,
total: res.data.supplierPage.pagination.total
}
)
} else {
cb(false)
}
})
})
export class SupplierManage extends PureComponent {
render() {
return (
<Card bodyStyle={{ padding: 10 }} >
<Search />
<List />
</Card>
)
}
}
不用装饰器的使用
const config ={
queryData: (params, pageInfo, state, cb) =>
querySupplierPage({ ...params, ...pageInfo }).then(res => {
if (res) {
cb(
{
dataSource: res.data.supplierPage.supplier_list,
total: res.data.supplierPage.pagination.total
}
)
} else {
cb(false)
}
})
}
class SupplierManage extends PureComponent {
render() {
return (
<Card bodyStyle={{ padding: 10 }} >
<Search />
<List />
</Card>
)
}
}
export default TablePage(config)(SupplierManage)
| 参数名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| defaultParams | object | {} | 搜索栏的默认参数 |
| queryData | function | 无/必填 | 列表请求函数 |
| pagination | boolean | true | 是否页码前端受控 |
| defaultPageInfo | object | { current_page: 1, page_size: 30 } | 页面的默认页码 |
| 参数名 | 类型 | 描述 |
|---|---|---|
| params | object | 表单数据 |
| pageInfo | object | 分页信息,避免后端不同字段,可以自行组装 |
| state | object | 组件的state |
| cb | function | 请求结果的回调函数,如果请求成功返回 {total,dataSource} 格式的回填数据,如果请求失败返回false |
| 参数名 | 类型 | 描述 |
|---|---|---|
| handleSearch | function | 列表搜索函数 |
| handleReset | function | 列表重置函数 |
| renderButtons | function | 返回按钮组,如果不想自己绑定函数,可以直接调用此函数 |
| loading | boolean | 数据加载状态 |
| form | object | form对象 |
| Item | ReactClass | 表单的Item组件 |
| 参数名 | 类型 | 描述 |
|---|---|---|
| handleReload | function | 列表变更后的数据重新请求函数 |
| setDataSoruce | function | 设置DataSoruce的函数 |
| dataSource | Array | 列表数据 |
| loading | boolean | 数据加载状态 |
| total | number | 总条数 |
| tableProps | object | 分配给table的props |
| 参数名 | 类型 | 描述 |
|---|---|---|
| loading | boolean | 数据加载状态 |
| pagination | object | 受控分页配置 |
| rowKey | string | 默认为 id |
| dataSource | Array | 列表数据 |
FAQs
a engine of analysis json to react
We found that igroot-table-page demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.

Company News
Socket is joining the OpenJS Security Stewardship Program to fund Node.js vulnerability research, maintainer remediation, and security releases.

Security News
Two compromised GitHub Actions were re-enabled with malicious tags intact, exposing thousands of downstream repositories to Mini Shai-Hulud.

Research
/Security News
A malicious Firefox extension fetches its payload after installation to evade detection, steal Google session cookies, and automate account takeover.