封装react antd的表格table组件
封装组件是为了能在开发过程中高度复用功能和样式相似的组件,以便我们只关注于业务逻辑层的处理,提高开发效率,提高逼格,降低代码重复率,降低劳动时间,减少加班的可能。
本次组件的封装采用了函数式组件即无状态组件的方式来提高页面渲染性能,由于无状态组件在数据变更后不会主动触发页面的重新渲染,所以本次的封装也用到了React Hooks。下面简要介绍一下函数式组件和React Hooks。
函数式组件是被精简成一个render方法的函数来实现的,由于是无状态组件,所以无状态组件就不会再有组件实例化的过程,无实例化过程也就不需要分配多余的内存,从而性能得到一定的提升。但函数式组件是没有this和ref的,如果强行给函数式组件添加ref会报一个Function components cannot be given refs
的错误。函数式组件也没有生命周期,没有所谓的componentWillMount、componentDidMount、componentWillReceiveProps、shouldComponentUpdate
等方法。
React Hooks是react16.8引入的特性,他允许你在不写class的情况下操作state和react的其他特性。Hook就是JavaScript函数,但是使用它们会有两个额外的规则:
只能在函数最外层调用Hook,不能在循环、条件判断或者子函数中调用;
只能在React的函数组件中调用Hook,不能在其他JavaScript函数中调用(自定义Hook除外)。
React Hooks中用的比较频繁的方法:
useState
useEffect
useContext
useReducer
useMemo
useRef
useImperativeHandle
由于以上方法的具体介绍及使用的篇幅过大,故请自行查阅API或资料,这里不再展开描述。
另外,本次封装一部分采用了JSX来创建虚拟dom节点,一部分采用了createElement方法来创建虚拟dom节点,createElement方法接收三个参数:
第一个参数:必填,可以是一个html标签名称字符串如span、div、p等,也可以是一个react组件;
第二个参数:选填,是创建的标签或组件的属性,用对象方式表示;
第三个参数:选填,是创建的标签或组件的子节点,可以是一个字符串或一个组件,也可以是一个包含了字符串或组件的数组,还可以是一个采用createElement创建的虚拟dom节点。
createElement方法可能用的人不会很多,因为现在有了类似于html的JavaScript语法糖JSX,使用和理解起来也较为直观和方便,符合我们对html结构的认知,但其实JSX被babel编译后的呈现方式就是使用createElement方法创建的虚拟dom,至于为何使用createElement方法,私心觉得可以提升编译打包效率。另外本次封装组件时有些地方也使用了JSX,是觉得在那些地方使用JSX更舒服,而有些地方使用createElement方法私心也觉得更符合js的编写习惯,如果你觉得在一个组件中既有JSX又有createElement会很乱的话,你可以统一使用一种即可。
本次封装所使用到的方法的介绍基本完毕,以下是组件封装的具体实现部分。
先贴一张最后实现的效果图:
1、所封装的antd table组件table.js
import React, { createElement, useState, useImperativeHandle } from 'react'
import PropTypes from 'prop-types'
import { Link } from "react-router-dom"
import { Table } from 'antd';
import { timestampToTime, currency } from '@/utils'
const h = createElement;
const TableComp = ({columns, dataSource, hasCheck, cRef, getCheckboxProps}) => {
const empty = '-',
[selectedRowKeys, setSelectedRowKeys ] = useState([]),
[selectedRows, setSelectedRows] = useState([]),
render = {
Default: v => {
if(!v) return empty
return v
},
Enum: (v, row, {Enum}) => {
if(!v || !Enum[v]) return empty
return Enum[v]
},
Loop: v => {
if(v.length < 1) return empty
return v.map((t, idx) => <span key={idx} style={{marginRight: '5px'}}>{t.total}</span>);
},
Action: (v, row, {action}) => {
let result = action.filter(n => {
let {filter = () => true} = n
return filter(row)
})
return result.map(c => <span className="table-link" onClick={() => c.click(row)} key={c.label}>{c.label}</span>)
},
Currency: v => {
if(!v) return empty
return currency(v)
},
Date: v => {
if(!v) return empty
return timestampToTime(v, 'second')
},
Link: (v, row, {url}) => {
if(!v) return empty
return <Link to={url}>{v}</Link>
}
}
columns = columns.map(n => {
let { type = 'Default', title, dataIndex, key } = n;
return {title, dataIndex, key, render: (v, row) => render[type](v, row, n) }
})
//父组件获取selectedRowKeys的方法-cRef就是父组件传过来的ref
useImperativeHandle(cRef, () => ({
//getSelectedRowKeys就是暴露给父组件的方法
getSelectedRowKeys: () => selectedRowKeys,
getSelectedRows: () => selectedRows
}));
const onSelectChange = (selectedRowKeys, selectedRows) => {
setSelectedRowKeys(selectedRowKeys);
setSelectedRows(selectedRows);
}
const rowSelection = {
selectedRowKeys,
onChange: onSelectChange,
getCheckboxProps: record => getCheckboxProps(record)
};
if(hasCheck) return h(Table, {columns, dataSource, rowSelection})
return h(Table, {columns, dataSource})
}
TableComp.propTypes = {
columns: PropTypes.array.isRequired, //表格头部
dataSource: PropTypes.array.isRequired, //表格数据
hasCheck: PropTypes.bool, //表格行是否可选择
cRef: PropTypes.object, //父组件传过来的获取组件实例对象或者是DOM对象
getCheckboxProps: PropTypes.func, //选择框的默认属性配置
}
export default TableComp
时间戳格式化timestampToTime.js
export const timestampToTime = (timestamp, type) => {
let date = new Date(timestamp); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
let Y = date.getFullYear() + '-';
let M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
let D = date.getDate() < 10 ? '0' + date.getDate() + ' ' : date.getDate() + '';
let h = date.getHours() < 10 ? '0' + date.getHours() + ':' : date.getHours() + ':';
let m = date.getMinutes() < 10 ? '0' + date.getMinutes() + ':' : date.getMinutes() + ':';
let s = date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds();
if (type == 'second') {
return Y + M + D + ' ' + h + m + s;
} else {
return Y + M + D
}
}
金额千分位currency.js
export const currency = v => {
let [n, d = []] = v.toString().split('.');
return [n.replace(/(\d)(?=(?:\d{3})+$)/g, '$1,')].concat(d).join('.');
};
简单介绍下封装的table组件,本组件基本涵盖了大多数情况下我们所用到的表格组件的情况,包括:操作按钮的权限控制、某一列的跳转、某一列的字段映射以及金额千分位、时间戳格式化和某一列数组数据的循环展示、表格是否可选择等等。如还有其他需求,可自行添加即可。
使用方法:
import React, { useRef } from 'react'
import { Button } from 'antd'
import Table from './components'
const TableDemo = () => {
const permission = ["handle", "pass", "refuse", "reApply", 'export'], Enum = {
CREATED: '代办理',
PASS: '待审批',
REJECT: '驳回',
REFUSE: '拒绝',
};
const columns = [
{ title: '姓名', dataIndex: 'name', key: 'name', type: 'Link', url: 'https://www.baidu.com' },
{ title: '年龄', dataIndex: 'age', key: 'age' },
{ title: '状态', dataIndex: 'status', key: 'status', type: 'Enum', Enum, },
{ title: '预警统计', dataIndex: 'statistic', key: 'statistic', type: 'Loop'},
{ title: '存款', dataIndex: 'money', key: 'money', type: 'Currency' },
{ title: '日期', dataIndex: 'date', key: 'date', type: 'Date'},
{ title: '操作', dataIndex: 'action', key: 'action', type: 'Action', action: [
{label: "查看", click: data => {console.log(data)}},
{label: "办理", click: data => {}, filter: ({status}) => status == 'CREATED' && permission.some(n => n == 'handle')},
{label: "通过", click: data => {}, filter: ({status}) => status == 'PASS' && permission.some(n => n == 'pass')},
{label: "驳回", click: data => {}, filter: ({status}) => status == 'REJECT' && permission.some(n => n == 'reject')},
{label: "拒绝", click: data => {}, filter: ({status}) => status == 'CREATED' && permission.some(n => n == 'refuse')},
{label: "重新付款", click: data => {}, filter: ({status}) => status == 'REAPPLY' && permission.some(n => n == 'reApply')},
]},
]
const dataSource = [
{key: 1, name: '小坏', age: 20, status: 'CREATED', date: 1596791666000, statistic: [{level: 3, total: 5}, {level: 2, total: 7}, {level: 1, total: 20}, {level: 0, total: 0}], money: 200000000000},
{key: 2, name: 'tnnyang', age: 18, status: 'PASS', date: 1596791666000, statistic: [], money: 2568912357893},
{key: 3, name: 'xiaohuai', status: 'REJECT', statistic: [], money: 6235871},
{key: 4, name: '陈公子', age: 21, status: 'REAPPLY', date: 1596791666000, statistic: []},
]
const config = {
columns,
dataSource,
hasCheck: true, //是否显示表格第一列的checkbox复选框
getCheckboxProps: record => {return {disabled: record.status == 'REJECT'}} //table表格rowSelection的禁用
}
//点击获取通过checkbox复选框选中的表格
const childRef = useRef();
const getTableChecked = () => {
const selectedRowKeys = childRef.current.getSelectedRowKeys(), selectedRows = childRef.current.getSelectedRows();
console.log(selectedRowKeys)
console.log(selectedRows)
}
return <div>
<Table {...config} cRef={childRef} />
<Button type="primary" onClick={getTableChecked}>获取选择的列表项</Button>
</div>
}
export default TableDemo
最后再贴一下本次封装所用到的各个包的版本:
react: 16.8.6,
react-dom: 16.8.6,
react-router-dom: 5.0.0,
antd: 4.3.5,
@babel/core: 7.4.4,
babel-loader: 8.0.5
其实最主要的是react和antd的版本,其中antd4和antd3在table组件上的差异还是很大的,在其他组件上的差异也是很大的。
封装react antd的表格table组件的更多相关文章
- 封装React AntD的dialog弹窗组件
前一段时间分享了基于vue和element所封装的弹窗组件(封装Vue Element的dialog弹窗组件),今天就来分享一个基于react和antD所封装的弹窗组件,反正所使用的技术还是那个技术, ...
- 封装react antd的form表单组件
form表单在我们日常的开发过程中被使用到的概率还是很大的,比如包含了登录.注册.修改个人信息.新增修改业务数据等的公司内部管理系统.而在使用时这些表单的样式如高度.上下边距.边框.圆角.阴影.高亮等 ...
- 封装react antd的upload上传组件
上传文件也是我们在实际开发中常遇到的功能,比如上传产品图片以供更好地宣传我们的产品,上传excel文档以便于更好地展示更多的产品信息,上传zip文件以便于更好地收集一些资料信息等等.至于为何要把上传组 ...
- React中使用Ant Table组件
一.Ant Design of React http://ant.design/docs/react/introduce 二.建立webpack工程 webpack+react demo下载 项目的启 ...
- react引用ant的table组件
import React from 'react';import '../../css/uicss/UI.css';import 'antd/lib/style/index.less';import ...
- React antd如何实现<Upload>组件上传附件再次上传已清除附件缓存问题。
最近在公司做React+antd的项目,遇到一个上传组件的问题,即上传附件成功后,文件展示处仍然还有之前上传附件的缓存信息,需要解决的问题是,要把上一次上传的附件缓存在上传成功或者取消后,可以进行清除 ...
- 十九、React UI框架Antd(Ant Design)的使用——及react Antd的使用 button组件 Icon组件 Layout组件 DatePicker日期组件
一.Antd(Ant Design)的使用:引入全部Css样式 1.1 antd官网: https://ant.design/docs/react/introduce-cn 1.2 React中使用A ...
- Ant Table组件
http://www.cnblogs.com/hujunzheng/p/5689650.html React中使用Ant Table组件 v一.Ant Design of React http:/ ...
- 解决react使用antd table组件固定表头后,表头和表体列不对齐以及配置fixed固定左右侧后行高度不对齐
一.固定表头后表体列和表头不对齐 此问题可能在antd3.24.0版本之前都存在,反正3.16.2版本是存在这个问题的,如果是3.24.0之前的版本估计只能通过修改css样式解决. 按照官网说的: 1 ...
随机推荐
- Linux find 查找 并删除文件 杀掉进程
find 默认在当前 即 . 目录下查找 du 文件名 / 目录 # 查看文件占用内存大小 1. 按照文件名查找 find / -name qwe # qwe为文件名 find / -name *qw ...
- 多国正在遭遇新型勒索病毒Petya侵袭
北京时间2017年6月27日晚,据外媒消息,多国正在遭遇 Petya 勒索病毒袭击,政府.银行.电力系统.通讯系统.企业以及机场都受到不同程度影响.请予关注,并做相应防范.相关事件描述及防范措施如下: ...
- PHP入门之函数
前言 之前对PHP的类型.运算符和流程控制简单说了一下.想了解的,这是地址. PHP入门之类型与运算符 PHP入门之流程控制 下面对函数简单说一下. 函数的基本概念 为完成某一个功能的程序指令的合集, ...
- 00_01_使用Parallels Desktop创建WindosXP虚拟机
打开paralles软件,选择文件->新建 继续 选择手动选择,之后勾选没有指定源也继续 选择要创建的操作系统(这里以XP为例,其他的windows系统安装基本都差不多) 根据需要选择,这里选择 ...
- 如何单页面不引用移动端的适配 (postcss)
由于pc端移动端同时开发所以同时有vant跟elementui,我的pc端登录界面直接引用之前项目做的 因为postcss全局引用,全局的px会自动转换自适应,然后页面的布局就呈现了放大的趋势, 查阅 ...
- pandas_一维数组与常用操作
# 一维数组与常用操作 import pandas as pd # 设置输出结果列对齐 pd.set_option('display.unicode.ambiguous_as_wide',True) ...
- bzoj 1515 [POI2006]Lis-The Postman 有向图欧拉回路
LINK:Lis-The Postman 看完题觉得 虽然容易发现是有向图欧拉回路 但是觉得很难解决这个问题. 先分析一下有向图的欧拉回路:充要条件 图中每个点的入度-出度=0且整张图是一个强连通分量 ...
- P3565 由简单的树形dp 引入 长链刨分
这道题感觉不太行 因为自己没想出来. 先说一下暴力吧,取三个点 让两两之间的距离相等怎么做呢,看起来是很复杂的样子的,但是仔细观察发现 答案出自一个点的儿子之间 或者儿子和父亲之间. 暴力枚举三个点然 ...
- EACCES: permission denied,mkdir … npm install 安装依赖问题解决
强哥最近在用hugeGraph图库做二次开发的时候,在打包的时遇到前端项目打包失败的问题: cwebp-bin@4.0.0 postinstall /home/hugegraph/my-hugegra ...
- SSM三大框架的整合
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 在Java后端开发领域,Spri ...