#说明
antd是基于 Ant Design 设计体系的 React UI 组件库,主要用于研发企业级中后台产品。也是是本人目前实习公司所用框架技术之一本笔记主要记录工作中项目中遇到的
与官方文档有差异化的的使用方式、或者是自己对于文档记录的组件的使用,方便自己查阅除此笔记外大家可以看我其他笔记 :全栈笔记、数据结构与算法、编程_前端开发学习笔记、编程_后台服务端学习笔记 、Java 、Nodejs 、JavaScript笔记、编程工具使用笔记 、ES6及后续版本学习笔记 、Vue笔记整合 、React笔记、微信小程序学习笔记、Chrome开发使用及学习笔记 以及许多其他笔记就不一一例举了
#目录
Ant Design of React 文档
一、数据录入
1、From表单
许多数据录入是与From表单相结合的
Ⅰ- 限制表单中输入框不能为空以及中文
通过
From.Item中的normalize属性进行处理对value的处理:组件获取值后进行转换,再放入 Form 中。不支持异步通过正则替换,将键入的空格以及中文替换为空字符串
代码示例
<Form form={form} onFinish={handleFinish}><Itemlabel="密码"name="password"rules={[{ required: true, message: '密码不能为空' }]}//密码框不允许为空格,且不允许输入中文normalize={(value) => value.replace(/\s/g, '').replace(/[\u4E00-\u9FA5]|[\uFE30-\uFFA0]/gi, '')}<Input.Passwordplaceholder="请输入密码"autoComplete="new-password"/></Item></From>
Ⅱ - 自定义校验
详见
Rule属性中自定义validator通常用作用户名等校验
<Form form={form} onFinish={handleFinish}><Itemlabel="用户名"name="username"validateTrigger="onBlur"normalize={(value) => value.replace(/\s/g, '')}rules={[//此处message为空字符串是为了防止下方自定义校验返回的字符串重叠{ required: true, message: '' },{validator: async (_, value) => {//如果是修改时,可以用这句话,当你内容没改变时,不进行校验if (editData.name === value) return;//判断空以及输入空字符串的报错if (value == null || value.trim() == '') return Promise.reject("用户名不能为空");//请求接口,查询通过上述两个校验后的字符串是否与数据库中重复,如果重复,则提示用户名已存在const res: IResult<IExist> = await ChannelApi.isUserExist( value );if (res?.data.status) return Promise.reject('用户名已存在');else return Promise.resolve();},},]}<Input placeholder="请输入用户名" /></Item></From>
- 通常用作必须字段校验(不进行数据库查询)
<Itemlabel="必填项"name="incomeType"rules={[{ required: true, message: '' },{validator: async (_, value) => {if (value == null || value.trim() == '')return Promise.reject('必填项不能为空');},},]}<Input.TextArea placeholder="请输入必填项信息" /></Item>
Ⅲ - 表单中动态修改数字输入框的value
出现场景:在 第一次对
InputNumber组件输入0时,就自动填充为设置的min了,这时我的需求是改成输入框失去焦点时再自动填充为min用到的组件:
From、InputNumber代码示例
```jsx //最小折扣,用于动态改变最小折扣 const [min, setMin] = useState(0);
addItem(‘yes_platforms’)}
>
> > <a name="a13b548f"></a>###### 效果展示> <a name="9e3466e8"></a># 二、数据展示<a name="5248efce"></a>## 1、[Table表格](https://ant.design/components/table-cn/)> 基本前端大部分页面数据展示都是使用`Table`进行展示<a name="7b6aa8bd"></a>### Ⅰ-列表渲染映射文字> 1.场景:当你对下列表渲染时,服务端传送过来的`值是数字`(0,1,2),而你要`显示成相对应的文字时`> 2.代码示例1:> ```jsx<Table><Columntitle="状态"dataIndex="status"render={(data) => {const text = {0: '已绑定',1: '未绑定',2: '已删除',};return text[data];}}/></Table>
- 代码示例2,写法不同效果相同,下面是本人喜欢的写法:
```jsx / 数据字典 company-const.ts / const SHOPSTATUSDICT = { 0: ‘已删除’, 1: ‘正常’, 2: ‘未绑定IP’, }; export{ SHOPSTATUSDICT }
/* 页面调用出 /
import { SHOPSTATUSDICT } from ‘../common/company-const’//导入数据字典
const columns = [ {
title: ‘状态’,
dataIndex: ‘status’,
ellipsis: true,
render: text=>SHOPSTATUSDICT[text]//进行状态数据映射
},]
return (
<a name="df8109cd"></a>### Ⅱ-列表渲染映射-小数转百分比> 1.当服务端给你的数据是小数,而你需要将其渲染成百分比进行展示 0.25-->25%> 2.解析:应用的是`render`相关知识点> 3.代码示例:> 4.转换函数代码```jsx/*** 将小数转化为百分比* @param point* @returns*/toPercent=(point:number)=>{//判断是否为空,如果为空不做处理 -->此处如果为空要转换成0,将此行代码下移一位即可if(!!!point) return point//服务端可能传来的数据是字符串,转换一下point=Number(point)if (point==0) return 0;let str=Number(point*100).toFixed()+"%";return str;}
- 列表table组件代码 ```jsx //写法一
(typeof data ==’number’)? tool.toPercent(data):data } />
//写法二 const columns = [ { title: ‘抽成比例’, dataIndex: ‘rate’, width: 150, ellipsis: true, //将小数转换成百分比 render: data => tool.toPercent(data)
},];
> 6.如果对于`if(!!!point)`此行代码不懂的同学可以看本人在js笔记中的[`js中为什么需要!!?`](https://gitee.com/hongjilin/hongs-study-notes/blob/master/%E7%BC%96%E7%A8%8B_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/(html+css+js)%E9%9B%B6%E6%95%A3%E7%AC%94%E8%AE%B0,%E5%BE%85%E6%A2%B3%E7%90%86/JavaScript%E7%AC%94%E8%AE%B0(%E9%9B%B6%E6%95%A3%E5%BE%85%E6%A2%B3%E7%90%86)/js%E4%B8%AD%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81!!%EF%BC%9F.md)部分<a name="e5b58ebe"></a>### Ⅲ-表格列固定> 1.需求场景:当你的列表过长时,使用滚轮进行拖动会导致用户体验感较差,这时就需要进行表格列固定> 2.未使用时效果> 2. 使用后效果> > <br />> `ps`:截图中展示的都是开发中的> `测试假数据`> 3.代码示例:只给出必要部分> 1.css样式代码(需要给定`width`,否则无法生效,给定高度,防止超出)```scss.tableWidth{width: 1600px;height: calc(100% - 48px);:global {.ant-table-wrapper,.ant-spin-nested-loading,.ant-spin-container,.ant-table-container {height: 100%;}.ant-table {height: calc(100% - 48px);}.ant-table-pagination.ant-pagination,div.ant-typography,.ant-typography p {margin-bottom: 0;}}}
- js调用代码示例1
const columns = [{title: '公司ID',fixed: 'left', //这就是固定在左边写法dataIndex: 'companyId',width: 150,ellipsis: true,},]return (<TableclassName={` ${style.tableWidth}`}columns={columns}scroll={{ x: 600 }}/>);
- js调用2:(都可实现,效果一样)
const columns = [{title: '名称',dataIndex: 'name',width: 150,fixed: 'left' as const,}, {title: '操作',dataIndex: 'agentId',width: 400,fixed: 'right' as const,}]return (<div className={style.tableWidth}><Tablescroll={{ x: 600, y: 'calc(100% - 48px)' }}columns={columns}/></div>);
- 注意:需要给定宽度,不然不会生效
Ⅳ-列表内容超出隐藏且悬停显示全
这属于
超长连续字段(长数字和长单词)破坏表格布局的问题(即使你指定了列的宽度也会被挤开),组件之前默认内加过word-break: break-word;去纠正此类布局,又会引起#13624的问题—列高也会被撑开(此处给的例子于其不一样,但原理相似)
- 需求场景:当我的列表内容过多使得表格撑开,导致整个表格样式与希望效果不符合时,我希望能将其超出隐藏,并能悬停显示全部信息
- 代码实现
import { Tooltip } from 'antd';const columns=[{ title: '渠道商账号', dataIndex: 'username',width: 150,onCell: () => {return {style: {maxWidth: 180,overflow: 'hidden',whiteSpace: 'nowrap',textOverflow:'ellipsis',cursor:'pointer'}}},//此处引入用作悬停显示全render: (text) => <Tooltip placement="topLeft" title={text}>{text}</Tooltip>},]
- 效果实现图
Ⅴ-Table表中使用气泡提示Tooltip
① AntD的Table表头title加Icon图标和气泡提示Tooltip
- 需求场景:当你的产品要你实现这个效果时
- 代码实现:直接在title中写即可
```tsx import React, { Component } from ‘react’; import { Table, Button, Modal, Typography } from ‘antd’; import { QuestionCircleOutlined } from ‘@ant-design/icons’; import { Tooltip } from ‘antd’; interface IProps { store: Store; }
const ManageTable = (props: IProps) => { const { store } = props; const columns = [ { dataIndex: ‘monthCount’, ellipsis: true, //效果实现就在这行 title:
]; return (
record.id || index} className=”table-box” columns={columns} /> ); };export default observer(ManageTable);
> 3. 效果展示> <a name="a95bc11f"></a>#### ②_列表中正常使用气泡提示Tooltip_> 1.正常列表中使用气泡提示> 2.代码示例:---在`columns`的render中使用> ```tsxconst columns = [ {title: '列名',dataIndex: '属性名',render: (text, record) => (<Tooltip placement="top" title={text}><a onClick={() => showModal(true, record.id, text)}>{text}</a></Tooltip>),},]
- 实现效果
③ 列表中使用[Tooltip]组件却出现两个提示的问题解决
- 问题场景:当你想为表格中超出隐藏文字部分加气泡提示时却发现出现两个提示
问题代码:
<Columntitle="支付宝账户"dataIndex="zfb_account_name"ellipsiswidth={120}render={text => (<Tooltip placement="top" title={text}>{/* {text} //此处直接将内容数据返回出去渲染 */}{`这是返回出去列表渲染的:${text}`}</Tooltip>)}/>
- 问题截图与分析:
.
- 问题分析:
在
render()中返回如果是纯文本,会被[Table]自动渲染成白色气泡提示,但此提示不符合我们自己的需求(无法复制、不够美观)所以我们返回给
render()的可以是自己定义的DOM.但是此处也会引出一个新的问题,看下方—>
- 初次改进代码:
-----------------------修改后出现问题的代码------------------------------------;<Columntitle="支付宝账户"dataIndex="zfb_account_name"ellipsiswidth={120}render={text => (<Tooltip placement="top" title={text}>{/* {text} //此处直接将内容数据返回出去渲染 */}<div>{`这是返回出去列表渲染的:${text}`}</div></Tooltip>)}/>
- 初次改进效果:
.
- 可以看出虽然解决了
双气泡提示的问题,但也引出了一个新问题::返回的新的DOM它不受前方ellipsis属性影响,虽然气泡提示成功变为只有一个,但是下方文本仍然超出,怎么办?
- 最正确写法(数组写法也一样,自行转换下即可):
- 代码
``tsx ----------------------- 正确写法1:给dom加以下样式 -----------------------------------; //tsx <Column title="支付宝账户" dataIndex="zfb_account_name" // ellipsis 此属性无法影响到render返回出来的dom节点,无用了,去除 width={120} render={text => ( <Tooltip placement="top" title={text}> {/* {text} //此处直接将内容数据返回出去渲染 */} <div className={style.text}>{这是返回出去列表渲染的:${text}`}
)} /> //scss .text { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } ———————————- 正确写法2:直接将写成内联样式(不推荐) —————————————————-;
> -效果截图:<br />> 于此问题完美解决了<a name="51ba2b2f"></a>### Ⅵ-table排序对比大小相关> antd列表排序`第一次点击逆序第二次正序第三次是恢复到默认`,依次循环.所以每第三次点击并不是无效,而是本身需要此效果> 其实可以直接写,只是如果不抽出,多处使用重复的代码,万一修改就很麻烦<a name="d5338c58"></a>#### ①_`table按时间排序`_> 1.需求场景分析:当你需要对列表中数据按照时间排序,但是antd默认排序方法无法认出根据你传入对象的何属性进行排序,此时你就需要自己写时间排序> 2.代码实现与截图> ```tsx//此处贴士:antd第一次点击逆序第二次正序第三次是回复到默认,依次循环{title: '采集结束时间',dataIndex: 'end_time',key: 'end_time',sorter: (a, b) => new Date(a.end_time).getTime() - new Date(b.end_time).getTime()},-----------------封装与调用--------------------------工具函数抽出:/*** 时间列表排序方法* 可以更换a,b顺序,做到初次为逆序还是正序排序* @param a 包含时间属性的对象a* @param b 包含时间属性的对象b* @param type 作为排序依据的时间属性名字* @returns number 利用正负数进行判断*/timeSorter = (a:object, b:object):Function => (type):number => new Date(a[type]).getTime() - new Date(b[type]).getTime()//此处b-a(看自己需求)原因为要符合服务端给定的数据,服务端给的数据默认越以前的时间在前面,防止第一次看上去无效调用: sorter: (a, b) => tool.timeSorter(b, a)('start_time')
②table通用对比大小
包括时间排序,你都能使用此封装函数
代码实现与截图
-----------------封装与调用--------------------------工具函数抽出:/*** 通用对比法* @param a 包含要对比属性的对象a* @param b 包含要对比属性的对象b* @param type 作为排序依据的属性名字* @returns boolean*///commonSorter = (a:object, b:object):Function=> (type):boolean => a[type] > b[type] -->错误,返回应为1或者-1commonSorter = (a:object, b:object):Function=> (type):number => a[type] > b[type] ? 1 : -1sorter={(a: object, b: object) => tool.commonSorter(a, b)('url')}
注意:排序返回应为正负数[如1、-1]而不是boolean类型
Ⅶ - 以其他列作为本列展示筛选条件
- 举个实际场景:
- 当我需要根据 [is_dynamic] 字段判断 本列展示的是 [IP名称] 还是 [IP地址] 时
- api概述: 列的 render() 方法自动接受两个参数
- 第一个参数: daraIndex 中绑定字段的值
- 第二个参数: 本行数据所有属性名与值
- 代码实现与截图
- 实现方法1:row含有本行所有字段
- 实现方法2:其实就是换个写法
2、Tree 树形控件
ps:下方解决代码只给出本效果所需必要代码,其余代码不展示出来—>
必须代码上都有相应注释
Ⅰ- 实现点击复选框后的文字也能进行选择的效果
- 需求场景:
- API概述:
- [
checkedKeys]API是显示记录表单中选中的节点- [
onCheck]API是针对前面的复选框点击,点击时传参数为所有选中的数组,此处可以直接看官方文档就能实现- [
onSelect]API是针对后面文字树节点的点击,但是点击时传参数为当前选中树节点,且其选中与未选中与[checkedKeys]无关联
- 思路分析:
- 首先,声明[
checkedKeys]变量,然后从服务端获取已有选中项,进行初始化- 不论是[onCheck]还是[onSelect],都是对于
checkedKeys变量进行拼装操作,再写入渲染- 只是说[onSelect]传来的参数需要经过加工,略显复杂,详情请看下方代码
- 代码:
```tsx import { Button, Form, Input, Tree } from ‘antd’; import { inject, observer, useLocalStore } from ‘mobx-react’; import React, { useEffect, useMemo, useRef, useState } from ‘react’; import style from ‘./style.scss’;
const EditModal = (props) => { //用来存 [checkedKeys]—>已经选中的状态 通常需要从服务端先获取初始化原先已经选中的数据 const [checkedKeys, setCheckedKeys] = useState([]); const [form] = Form.useForm();
/**
- 一 复选框选中函数
- @param checked 传入当前勾选上的所有节点key / const handleSearchTreeNode = (checked) => { setCheckedKeys(checked); }; /*
- 二 树节点选中函数
- @param checked 选中时传入当前树节点 —注意:当为未选中状态时传入为空,所以不能用作[权限选中判断]
- @param e 点击树节点时传入整个树节点数据信息 —不论是否选中都会传入
- @param node
@param event */ const handleSelectTreeNode = (checked, e, node, event) => { //将点击的树节点的[key]解构出来 const { node: { key }, } = e; //声明一个SET数组,将key存入(以防万一同时防止重复赋值) const data = Array.from(new Set([…checkedKeys, key])); //首先判断原有[树数组:checkedKeys]中是否含有当前点击的[key],如果有则筛选掉, if (checkedKeys.includes(key)) setCheckedKeys(checkedKeys.filter((value) => value != key)); //如果原有[树数组]中不含有,则直接将新增好的[data]写入替代掉[树数组:checkedKeys] else setCheckedKeys(data); };
return (
<Form.Item name="roles"noStylerules={[() => ({validator(rule: any, value: any) {if (checkedKeys && checkedKeys.length === 0) return Promise.reject('请选择角色对应的权限');return Promise.resolve();},}),]}
>
<TreedefaultCheckedKeys={[]}checkableexpandedKeys={expandedKeys}onExpand={(keys) => {setExpandedKeys(keys);}}//此处绑定所有Tree数据treeData={menuTree}//此处绑定选中的keycheckedKeys={checkedKeys}//此处为复选框点击触发APIonCheck={handleSearchTreeNode}//此处为后面的文字树节点点击触发APIonSelect={handleSelectTreeNode}height={300}/>
); }; ```
- 效果展示:
3、Tooltip文字提示
Ⅰ - 自定义悬停提示
一般我们的悬停提示就是直接将数据赋值到 [title] 上,但是目前遇到一个需求,是要求悬停提示需要换行、指定行带颜色
实际上 [ title ] 可以接受参数是一个ReactNode 即直接一个节点
<Tooltip title={this.remarksNode(remarks, remarks_v5, yes_platforms, no_platforms)}><p className={style.remarks}>{data}</p></Tooltip>// 生成ReactNode 函数const remarksNode = (remarks, remarks_v5, yes_platforms, no_platforms) => {return (<div className={style.zz}><span>3版本提示语:</span><span>{remarks}</span><span> 5版本提示语:</span><span> {remarks_v5}</span><span>常见可用平台: {yes_platforms?.toString()}</span><span style={{color:'red'}}>不推荐使用平台: {no_platforms?.toString()}</span></div>);};效果展示




.
.






