跳至主要內容

antd

chanchaw大约 5 分钟react

覆盖官方样式

找到要修改的官方默认的类名,使用 global 保护起来后再修改,相反,如果不使用 global 无法修改。

:global(.ant-btn-primary) {
    background-color: red;
}

官方样式源码open in new window 的目录 es 下有各个组件的样式,比如按钮的样式主文件是 antd/es/button/style/index.js

封装组件

封装组件 Button 为经过权限过滤的按钮,如果没有权限则不显示

菜单

码云仓库open in new window 的分支 mytools 的提交 e760c1cf27480542d70ac6a2b471827115afdd26 中使用 antd.menu 制作了组件 src/component/Menu 其中通过配置文件 src/component/Menu/config.ts 将二维数组生成树形左侧菜单的数据,该组件中同时封装了多个功能

  • 根据名称返回 @ant-design/icons 图标组件的函数 getIcon
  • 生成菜单项对象的函数 getAntdMenuItem
  • 将二维数组生成树形菜单的函数 generatMenuItemList,返回的结果应用到 antd.Menu.items 属性上即可

图标

根据名称获取图标

import React from 'react'
import * as Icons from '@ant-design/icons'

// 传入图标的名称,返回 antd 的图标
function getIcon(name?:string){
    if(!name) return <></>
    const customerIcons:{[key:string]:any} = Icons
    const icon = customerIcons[name]
    if(!icon) return <></>
    return React.createElement(icon)
}

官方

国内官网open in new windowgithub仓库open in new window

2024年8月19日 10:00:32 官方案例面包屑的数据类型是 [{title: 路径名称}],在项目中封装面包屑的代码如下

遍历树形获路径字符串数组1/2
export default {
  /**
   * 获取指定路由的全路径字符串数组,用于显示在 breadCrumb
   * @param treeNodeList 树形菜单
   * @param url 目标路径名称
   * @param pathArr 初次调用传入空数组
   * @returns
   */
  getLeafPath: function getLeafPath(treeNodeList: Array<MyType.MenuItem>, url: string, pathArr: string[]): string[] {
    if (!treeNodeList) return treeNodeList
    for (const item of treeNodeList) {
      pathArr.push(item.label)
      if (item.url === url) return pathArr
      if (item.children?.length) {
        const list = getLeafPath(item.children, url, pathArr)
        if (list?.length) return list
      }
      pathArr.pop()
    }
    return []
  }
}

封装 antd.Breadcrumb2/2
import { useEffect, useState } from 'react'
import { Breadcrumb } from 'antd'
import styles from './index.module.less'
import { useLocation } from 'react-router-dom'
import utils from '@/utils'
import { menuItems } from '../Menu/config'

function BreadCrumb() {
  const { pathname } = useLocation()
  const [breadCrumb, setBreadCrumb] = useState<{ title: string }[]>()

  const getBreadCrumb = (stringArr: string[]): { title: string }[] => {
    if (!stringArr || stringArr.length === 0) return []
    const ret: { title: string }[] = []
    stringArr.forEach(item => ret.push({ title: item }))
    return ret
  }
  useEffect(() => {
    const breadCrumbStringArr = utils.getLeafPath(menuItems, pathname, [])
    setBreadCrumb(getBreadCrumb(breadCrumbStringArr))
  }, [pathname])
  return <Breadcrumb className={styles.breadcrumb} items={breadCrumb} />
}

export default BreadCrumb

Select

<Select>
    {
        cityList.map(item => {
            return <Select.Option key={item.id} value={item.id}>item.name</Select.Option>
        })
    }
</Select>

Table

表格中的枚举

渲染函数的第一个参数是当前列的数据,第二个参数是当前行的数据

// 格式化表格中的日期时间类型
{
    title: '更新时间',
    dataIndex: 'updateTime',
    key:'updateTime',
    render(currentColVal, currentRowVal){
        return formatDate(currentColVal)        
    }
}

// 设置表格中的枚举值
{
    title:'菜单类型',
    dataIndex: 'menuType',
    key:'menuType',
    render(menuType){
        return {
            1: '菜单',
            2: '按钮',
            3: '页面'
        }[menuType]
    }
}

Form

默认值

<Form form={form} initialValues={{menuState: 1}}>
</Form>

变动检测

可通过属性 shouldUpdate 检测某个表单项变动后执行业务逻辑,见官网介绍open in new window。动态加载表单项的案例如下

使用案例

import { Form } from 'antd'
const [form] = Form.useForm()
<Form form={form} labelCol={{ span: 3 }} labelAlign='right'>
</Form>

执行校验

执行校验的方法 validateFields 是异步方法,如果不使用 async+await ,需要用嵌套回调的方法写代码。即校验成功的后续代码都写在 then 里面。当校验不通过时逻辑会流到 catch 分支中。

  const handleSubmitChanCalls = () => {
    form
      .validateFields()
      .then(res => {
        console.log('表单验证的结果是', res)
      })
      .catch(err => {
        message.error('请查看报错提示,修复后重试!')
        return
      })
  }

获取数据、清除

const formValues = form.getFieldsValue() // 获取表单数据
form.resetFields() // 重置表单

message

常规的使用要求必须在 react 组件中才能使用 message,如果要自己封装的 request.ts 中使用浏览器控制台会报错 Warning: [antd: message] Static function can not consume context like dynamic theme. Please use 'App' component instead.

为解决该问题需要做如下步骤

创建无视图全局组件1/3

创建组件 src/utils/AntdGlobal.tsx,全部代码如下:

import { App } from 'antd'
import type { MessageInstance } from 'antd/es/message/interface'
import type { ModalStaticFunctions } from 'antd/es/modal/confirm'
import type { NotificationInstance } from 'antd/es/notification/interface'

let message: MessageInstance
let notification: NotificationInstance
let modal: Omit<ModalStaticFunctions, 'warn'>

export default () => {
  const staticFunction = App.useApp()
  message = staticFunction.message
  modal = staticFunction.modal
  notification = staticFunction.notification
  return null
}

export { message, notification, modal }
根组件中应用2/3

在根组件 src/App.tsx 中导入并使用该组件

import './App.css'
import { RouterProvider } from 'react-router-dom'
import router from './router'
import { ConfigProvider, App as AntdApp } from 'antd'
import AntdGlobal from './utils/AntdGlobal'

function App() {
  return (
    <ConfigProvider
      theme={{
        token: { colorPrimary: '#ed6c00' }
      }}
    >
      <AntdApp>
        <AntdGlobal />
        <RouterProvider router={router} />
      </AntdApp>
    </ConfigProvider>
  )
}
export default App
非组件中使用3/3

在自己封装的 src/utils/request.ts 中使用

import { message } from './AntdGlobal'
message.info('xxxxxx')

那么可以同样的方法在业务组件中使用。

或者使用官方推荐的方法如下:

import { App } from 'antd'
function Login(){
    const { message, notification, modal} = App.useApp()
    message.info('xxxxx')
}
export default Login

全局配置

全局尺寸

下图是根据 官网介绍全局配置的文章open in new window 制作的项目全局配置,应用在 react-manageropen in new window 的分支 mytoolscommit:fb82569185eb4ae2f1e25494eb34f088d010d6cb

主题色

antd 提供自定义主题色的功能,通过 ConfigProvider 包裹 app 根组件

import './App.css'
import { RouterProvider } from 'react-router-dom'
import router from './router'
import { ConfigProvider } from 'antd'

function App() {
  return (
    <ConfigProvider
      theme={{
        token: { colorPrimary: '#ed6c00' }
      }}
    >
      <RouterProvider router={router} />
    </ConfigProvider>
  )
}

export default App