写点什么

Ant Design 6.0 尝鲜:上手现代化组件开发|得物技术

作者:得物技术
  • 2025-12-23
    上海
  • 本文字数:18775 字

    阅读完需:约 62 分钟

Ant Design 6.0 尝鲜:上手现代化组件开发|得物技术

一、引言

组件体验的革新

在前端开发领域,Ant Design 一直是企业级 React 应用的首选 UI 库之一。随着 Ant Design 6.0 的发布,我们又见证了一次聚焦于组件功能与用户体验的革新。本次更新不仅引入了多个全新组件,更对现有核心组件进行了功能性增强,使开发者能够以更少的代码实现更丰富的交互效果。

二、Masonry 瀑布流组件:智能动态布局

传统网格布局在处理高度不一的元素时常出现大量空白区域,Masonry(瀑布流)布局则完美解决了这一问题。Ant Design 6.0 全新推出的 Masonry 组件让实现这种流行布局变得异常简单。

基础实现与响应式配置

import { useState, useEffect, useRef } from "react";import { Masonry, Card, Image, Spin } from "antd";/** * Masonry瀑布流页面 */export default () => {  const [isLoading, setIsLoading] = useState(false);  const containerRef = useRef<HTMLDivElement>(null);  const isLoadingRef = useRef(false);  const imageList = [    "https://images.xxx.com/photo-xxx-4b4e3d86bf0f",    ...    "https://images.xxx.com/photo-xxx-98f7befd1a60",  ];  const titles = [    "山间日出",    ...    "自然风光",  ];  const descriptions = [    "清晨的第一缕阳光",    ...    "色彩鲜艳的料理",  ];  const heights = [240, 260, 280, 300, 320, 350, 380, 400];  // Mock数据生成函数  const generateMockData = (startIndex: number, count: number) => {    return Array.from({ length: count }, (_, index) => ({      id: startIndex + index + 1,      src: imageList[Math.floor(Math.random() * imageList.length)],      title: titles[(startIndex + index) % titles.length],      description: descriptions[(startIndex + index) % descriptions.length],      height: heights[Math.floor(Math.random() * heights.length)],    }));  };  // 初始数据:20条  const [photoItems, setPhotoItems] = useState(() => generateMockData(0, 20));  // 滚动监听  useEffect(() => {    isLoadingRef.current = isLoading;  }, [isLoading]);  useEffect(() => {    const loadMoreData = async () => {      if (isLoadingRef.current) return;      isLoadingRef.current = true;      setIsLoading(true);      // 模拟API请求延迟      await new Promise((resolve) => setTimeout(resolve, 500));      setPhotoItems((prev) => {        const newItems = generateMockData(prev.length, 10);        return [...prev, ...newItems];      });      isLoadingRef.current = false;      setIsLoading(false);    };    const checkScroll = () => {      if (isLoadingRef.current) return;      const container = containerRef.current;      if (!container) return;      const scrollTop = container.scrollTop;      const scrollHeight = container.scrollHeight;      const clientHeight = container.clientHeight;      // 当滚动到距离底部100px时触发加载      if (scrollTop + clientHeight >= scrollHeight - 100) {        loadMoreData();      }    };    const handleWindowScroll = () => {      if (isLoadingRef.current) return;      const windowHeight = window.innerHeight;      const documentHeight = document.documentElement.scrollHeight;      const scrollTop =        window.pageYOffset || document.documentElement.scrollTop;      // 当滚动到距离底部100px时触发加载      if (scrollTop + windowHeight >= documentHeight - 100) {        loadMoreData();      }    };    const container = containerRef.current;    // 初始检查一次,以防内容不足一屏    setTimeout(() => {      checkScroll();      handleWindowScroll();    }, 100);    // 监听容器滚动    if (container) {      container.addEventListener("scroll", checkScroll);    }    // 同时监听 window 滚动(作为备选)    window.addEventListener("scroll", handleWindowScroll);    return () => {      if (container) {        container.removeEventListener("scroll", checkScroll);      }      window.removeEventListener("scroll", handleWindowScroll);    };  }, []);  return (    <div ref={containerRef} className="w-full h-[100vh] overflow-auto p-[24px]">      <Masonry        // 响应式列数配置        columns={{ xs: 2, sm: 3, md: 4, lg: 5 }}        // 列间距与行间距        gutter={16}        items={photoItems as any}        itemRender={(item: any) => (          <Card            key={item.id}            hoverable            cover={              <div style={{ height: item.height, overflow: "hidden" }}>                <Image                  src={item.src}                  alt={item.title}                  height={item.height}                  width="100%"                  style={{                    width: "100%",                    height: "100%",                    objectFit: "cover",                  }}                  preview={{                    visible: false,                  }}                />              </div>            }            styles={{              body: {                padding: "12px",              },            }}          >            <Card.Meta title={item.title} description={item.description} />            <div              className="mt-[8px] text-[12px] text-[#999]"            >              图片 #{item.id}            </div>          </Card>        )}      />      {isLoading && (        <div          className="flex items-center justify-center p-[20px] text-[#999]"        >          <Spin style={{ marginRight: "8px" }} />          <span>加载中...</span>        </div>      )}    </div>  );};
复制代码




布局效果说明

Masonry 组件会根据设定的列数自动将元素排列到高度最小的列中。与传统的网格布局相比,这种布局方式能有效减少内容下方的空白区域,特别适合展示高度不一的内容块。


对于图片展示类应用,这种布局能让用户的视线自然流动,提高浏览的沉浸感和内容发现率。

三、Tooltip 平滑移动:优雅的交互引导

在 Ant Design 6.0 中,Tooltip 组件引入了独特的平滑过渡效果,通过 ConfigProvider 全局配置的 tooltip.unique 配置项,当用户在多个带有提示的元素间移动时,提示框会以流畅的动画跟随,而不是突然消失和重现。

实现平滑跟随效果

import { Tooltip, Button, Card, ConfigProvider } from "antd";import {  UserOutlined,  SettingOutlined,  BellOutlined,  MailOutlined,  AppstoreOutlined,} from "@ant-design/icons";import { TooltipPlacement } from "antd/es/tooltip";/** * Tooltip 示例 */export default () => {  const buttonItems = [    {      icon: <UserOutlined />,      text: "个人中心",      tip: "查看和管理您的个人资料",      placement: "top",    },    {      icon: <SettingOutlined />,      text: "系统设置",      tip: "调整应用程序参数和偏好",      placement: "top",    },    {      icon: <BellOutlined />,      text: "消息通知",      tip: "查看未读提醒和系统消息",      placement: "top",    },    {      icon: <MailOutlined />,      text: "邮箱",      tip: "收发邮件和管理联系人",      placement: "bottom",    },    {      icon: <AppstoreOutlined />,      text: "应用中心",      tip: "探索和安装更多应用",      placement: "bottom",    },  ];  return (    <div className="w-full h-[100vh] overflow-auto p-[24px] space-y-5">      <ConfigProvider        tooltip={{          unique: true,        }}      >        <Card title="平滑过渡导航工具栏" bordered={false}>          <div className="flex justify-center gap-6 py-10 px-5 bg-gradient-to-br from-[#f5f7fa] to-[#c3cfe2] rounded-3xl">            {buttonItems.map((item, index) => (              <Tooltip                placement={item.placement as TooltipPlacement}                key={index}                title={                  <div>                    <div className="font-bold mb-1">{item.text}</div>                    <div className="text-xs text-[#fff]/60">{item.tip}</div>                  </div>                }                color="#1677ff"              >                <Button                  type="primary"                  shape="circle"                  icon={item.icon}                  size="large"                  className="w-[60px] h-[60px] text-2xl shadow-md transition-all duration-300 ease-in-out"                />              </Tooltip>            ))}          </div>          <div className="mt-5 p-4 bg-green-50 border border-green-300 rounded-md">            <div className="flex items-center">              <div className="w-3 h-3 rounded-full bg-green-500 mr-2"></div>              <span>                提示:尝试将鼠标在不同图标间快速移动,观察 Tooltip                的平滑过渡效果              </span>            </div>          </div>        </Card>      </ConfigProvider>      <Card title="非平滑过渡导航工具栏" bordered={false}>        <div className="flex justify-center gap-6 py-10 px-5 bg-gradient-to-br from-[#f5f7fa] to-[#c3cfe2] rounded-3xl">          {buttonItems.map((item, index) => (            <Tooltip              key={index}              placement={item.placement as TooltipPlacement}              title={                <div>                  <div className="font-bold mb-1">{item.text}</div>                  <div className="text-xs text-[#fff]/60">{item.tip}</div>                </div>              }              color="#1677ff"            >              <Button                type="primary"                shape="circle"                icon={item.icon}                size="large"                className="w-[60px] h-[60px] text-2xl shadow-md transition-all duration-300 ease-in-out"              />            </Tooltip>          ))}        </div>        <div className="mt-5 p-4 bg-green-50 border border-green-300 rounded-md">          <div className="flex items-center">            <div className="w-3 h-3 rounded-full bg-green-500 mr-2"></div>            <span>              提示:尝试将鼠标在不同图标间快速移动,观察 Tooltip 的非平滑过渡效果            </span>          </div>        </div>      </Card>    </div>  );};
复制代码



交互效果说明

当 tooltip.unique 设置为 true 时,用户在不同元素间移动鼠标时,Tooltip 会呈现以下行为:


  1. 平滑位置过渡:Tooltip 不会立即消失,而是平滑移动到新目标位置

  2. 内容无缝切换:提示内容在新位置淡入,旧内容淡出

  3. 视觉连续性:保持同一时刻只有一个 Tooltip 显示,避免界面混乱


这种设计特别适合工具栏、导航菜单等元素密集的区域,能有效降低用户的认知负荷,提供更加流畅的交互体验。

四、InputNumber 拨轮模式:直观的数字输入

数字输入框是表单中的常见组件,但传统的上下箭头控件在小屏幕或触摸设备上操作不便。Ant Design 6.0 的 InputNumber 组件新增了 mode="spinner" 属性,提供了更直观的“加减按钮”界面。

拨轮模式实现

import { InputNumber, Card, Row, Col, Typography, Space } from "antd";import {  ShoppingCartOutlined,  DollarOutlined,  GiftOutlined,} from "@ant-design/icons";const { Title, Text } = Typography;/** * InputNumber 示例 */export default () => {  return (    <div className="w-full h-[100vh] overflow-auto p-[24px] space-y-5">      <Card title="商品订购面板" bordered={false}>        <Row gutter={[24, 24]}>          <Col span={8}>            <div className="text-center">              <div className="w-[80px] h-[80px] mx-auto mb-4 rounded-3xl bg-[#f0f5ff] flex items-center justify-center text-[32px] text-[#1677ff]">                <ShoppingCartOutlined />              </div>              <Title level={5} className="mb-3">                购买数量(非数字拨轮)              </Title>              <InputNumber                min={1}                max={50}                defaultValue={1}                size="large"                className="w-[250px]!"                addonBefore="数量"              />              <div className="mt-2 text-xs text-gray-600">限购50件</div>            </div>          </Col>          <Col span={8}>            <div className="text-center">              <div className="w-[80px] h-[80px] mx-auto mb-4 rounded-3xl bg-[#fff7e6] flex items-center justify-center text-[32px] text-[#fa8c16]">                <DollarOutlined />              </div>              <Title level={5} className="mb-3">                折扣力度(数字拨轮)              </Title>              <InputNumber                min={0}                max={100}                defaultValue={10}                mode="spinner"                size="large"                formatter={(value) => `${value ?? 0}%`}                parser={(value) =>                  Number.parseFloat(value?.replace("%", "") ?? "0") as any                }                className="w-[250px]!"                addonBefore="折扣"              />              <div className="mt-2 text-xs text-gray-600">0-100%范围</div>            </div>          </Col>          <Col span={8}>            <div className="text-center">              <div className="w-[80px] h-[80px] mx-auto mb-4 rounded-3xl bg-[#f6ffed] flex items-center justify-center text-[32px] text-[#52c41a]">                <GiftOutlined />              </div>              <Title level={5} className="mb-3">                礼品数量(数字拨轮,自定义加减按钮)              </Title>              <Space.Compact block className="justify-center!">                <Space.Addon>                  <span>礼品</span>                </Space.Addon>                <InputNumber                  min={0}                  max={10}                  defaultValue={0}                  mode="spinner"                  size="large"                  className="w-[250px]!"                  controls={{                    upIcon: <span className="text-base">➕</span>,                    downIcon: <span className="text-base">➖</span>,                  }}                />              </Space.Compact>              <div className="mt-2 text-xs text-gray-600">每单最多10份</div>            </div>          </Col>        </Row>        <div className="mt-8 p-4 bg-[#fff0f6] rounded-lg border border-dashed border-[#ffadd2]">          <Text type="secondary">            <strong>设计提示:</strong>            拨轮模式相比传统箭头控件,提供了更大的点击区域和更明确的视觉反馈,特别适合触摸设备和需要频繁调整数值的场景。加减按钮的分离式设计也降低了误操作的可能性。          </Text>        </div>      </Card>    </div>  );};
复制代码



交互优势分析

拨轮模式相比传统数字输入框具有明显优势:


  1. 触摸友好:更大的按钮区域适合移动端操作

  2. 意图明确:“+”和“-”符号比小箭头更直观

  3. 快速调整:支持长按连续增减数值

  4. 视觉反馈:按钮有明确的状态变化(按下、悬停)


在电商、数据仪表盘、配置面板等需要频繁调整数值的场景中,这种设计能显著提升用户的操作效率和满意度。

五、Drawer 拖拽调整:灵活的侧边面板

抽屉组件常用于移动端导航或详情面板,但固定尺寸有时无法满足多样化的内容展示需求。Ant Design 6.0 为 Drawer 组件新增了 resizable 属性,允许用户通过拖拽边缘实时调整面板尺寸。

可调整抽屉实现

import { Drawer, Button, Card, Typography, Divider, List, Flex } from "antd";import {  DragOutlined,  CalendarOutlined,  FileTextOutlined,  TeamOutlined,  CommentOutlined,  PaperClipOutlined,} from "@ant-design/icons";import { useState } from "react";import { DrawerResizableConfig } from "antd/es/drawer";const { Title, Text, Paragraph } = Typography;/** * Drawer 示例 */export default () => {  const [open, setOpen] = useState(false);  const [drawerWidth, setDrawerWidth] = useState(400);  const [resizable, setResizable] = useState<boolean | DrawerResizableConfig>(    false,  );  const tasks = [    { id: 1, title: "完成项目需求文档", time: "今天 10:00", priority: "high" },    { id: 2, title: "团队周会", time: "今天 14:30", priority: "medium" },    { id: 3, title: "代码审查", time: "明天 09:00", priority: "high" },    { id: 4, title: "客户演示准备", time: "后天 15:00", priority: "medium" },  ];  const showDrawerWithResizable = () => {    setOpen(true);    setDrawerWidth(400);    setResizable({      onResize: (size) => {        setDrawerWidth(size);      },    });  };  const showDrawerWithoutResizable = () => {    setOpen(true);    setDrawerWidth(600);    setResizable(false);  };  const onClose = () => {    setOpen(false);  };  return (    <div className="w-full h-[100vh] flex items-center justify-center overflow-auto p-[24px] space-y-5">      <Card        title="任务管理面板"        variant="outlined"        className="max-w-[800px] mx-auto"      >        <div className="py-10 px-5 text-center">          <div className="w-20 h-20 mx-auto mb-6 rounded-full bg-[#1677ff] flex items-center justify-center text-[36px] text-white">            <DragOutlined />          </div>          <Title level={3}>可调整的任务详情面板</Title>          <Paragraph type="secondary" className="max-w-[600px] my-4 mx-auto">            点击下方按钮打开一个可拖拽调整宽度的抽屉面板。尝试拖动抽屉左侧边缘,根据内容需要调整面板尺寸。          </Paragraph>          <Flex justify="center" gap={10}>            <Button              type="primary"              size="large"              onClick={showDrawerWithResizable}              icon={<CalendarOutlined />}              className="mt-6"            >              打开任务抽屉(可拖拽宽度)            </Button>            <Button              type="primary"              size="large"              onClick={showDrawerWithoutResizable}              icon={<CalendarOutlined />}              className="mt-6"            >              打开任务抽屉(不可拖拽宽度)            </Button>          </Flex>        </div>      </Card>      <Drawer        title={          <div className="flex items-center">            <CalendarOutlined className="mr-2 text-[#1677ff]" />            <span>任务详情与计划</span>            {resizable && (              <div className="ml-3 py-0.5 px-2 bg-[#f0f5ff] rounded-[10px] text-xs text-[#1677ff]">                可拖拽调整宽度              </div>            )}          </div>        }        placement="right"        onClose={onClose}        open={open}        size={drawerWidth}        resizable={resizable}        extra={          <Button type="text" icon={<DragOutlined />}>            {resizable ? "拖拽边缘调整" : "不可拖拽"}          </Button>        }        styles={{          body: {            paddingTop: "12px",          },          header: {            borderBottom: "1px solid #f0f0f0",          },        }}      >        <div className="mb-6">          <div className="flex items-center mb-4">            <FileTextOutlined className="mr-2 text-[#52c41a]" />            <Title level={5} className="m-0">              当前任务            </Title>          </div>          <Card size="small">            <List              itemLayout="horizontal"              dataSource={tasks}              renderItem={(item) => (                <List.Item>                  <List.Item.Meta                    avatar={                      <div                        className={`w-8 h-8 rounded-md flex items-center justify-center ${                          item.priority === "high"                            ? "bg-[#fff2f0] text-[#ff4d4f]"                            : "bg-[#f6ffed] text-[#52c41a]"                        }`}                      >                        {item.priority === "high" ? "急" : "常"}                      </div>                    }                    title={<a>{item.title}</a>}                    description={<Text type="secondary">{item.time}</Text>}                  />                </List.Item>              )}            />          </Card>        </div>        <Divider />        <div className="mb-6">          <div className="flex items-center mb-4">            <TeamOutlined className="mr-2 text-[#fa8c16]" />            <Title level={5} className="m-0">              团队动态            </Title>          </div>          <Paragraph>            本周团队主要聚焦于项目第三阶段的开发工作,前端组已完成了核心组件的重构,后端组正在进行性能优化。          </Paragraph>        </div>        <div className="mb-6">          <div className="flex items-center mb-4">            <CommentOutlined className="mr-2 text-[#722ed1]" />            <Title level={5} className="m-0">              最新反馈            </Title>          </div>          <Card size="small" type="inner">            <Paragraph>              "新的界面设计得到了客户的积极反馈,特别是可调整的面板设计,让不同角色的用户都能获得适合自己工作习惯的布局。"            </Paragraph>            <Text type="secondary">—— 产品经理,XXX</Text>          </Card>        </div>        <div>          <div className="flex items-center mb-4">            <PaperClipOutlined className="mr-2 text-[#eb2f96]" />            <Title level={5} className="m-0">              使用提示            </Title>          </div>          <div className="p-3 bg-[#f6ffed] rounded-md border border-[#b7eb8f]">            <Text type="secondary">              当前抽屉宽度: <strong>{drawerWidth}px</strong>。您可以: 1.              拖动左侧边缘调整宽度 2. 内容区域会根据宽度自动重新布局 3.              适合查看不同密度的信息            </Text>          </div>        </div>      </Drawer>    </div>  );};
复制代码




拖拽交互的价值

可调整抽屉的设计带来了明显的用户体验提升:


  1. 自适应内容:用户可以根据当前查看的内容类型调整面板尺寸

  2. 个性化布局:不同用户或场景下可以设置不同的面板大小

  3. 多任务处理:宽面板适合详情查看,窄面板适合边操作边参考

  4. 渐进式披露:可以从紧凑视图逐步展开到详细视图

六、Modal 背景模糊:朦胧美学的视觉升级

在传统 Web 应用中,模态框的遮罩层往往是简单的半透明黑色,视觉效果单调且缺乏现代感。而在 iOS 和 macOS 等系统中,毛玻璃(frosted glass)效果已成为标志性的设计语言效果样式。Ant Design 6.0 为所有弹层组件引入了原生背景模糊支持,并提供了强大的语义化样式定制能力,让开发者能轻松打造出高级感十足的视觉效果。

背景模糊与语义化样式定制

以下示例展示了如何结合 Ant Design 6.0 的背景模糊特性和 antd-style 库,实现两种不同风格的模态框:


import { useState } from "react";import { Button, Flex, Modal, Card, Image, Typography, Space } from "antd";import type { ModalProps } from "antd";import { createStyles } from "antd-style";const { Title, Text } = Typography;// 使用 antd-style 的 createStyles 定义样式const useStyles = createStyles(({ token }) => ({  // 用于模态框容器的基础样式  container: {    borderRadius: token.borderRadiusLG * 1.5,    overflow: "hidden",  },}));// 示例用的共享内容const sharedContent = (  <Card size="small" bordered={false}>    <Image      height={300}      src="https://gw.alipayobjects.com/zos/antfincdn/LlvErxo8H9/photo-1503185912284-5271ff81b9a8.webp"      alt="示例图片"      preview={false}      className="mx-auto!"    />    <Text type="secondary" style={{ display: "block", marginTop: 8 }}>      Ant Design 6.0 默认的模糊背景与 antd-style      定制的毛玻璃面板相结合,营造出深邃而富有层次的视觉体验。    </Text>  </Card>);export default () => {  const [blurModalOpen, setBlurModalOpen] = useState(false);  const [gradientModalOpen, setGradientModalOpen] = useState(false);  const { styles: classNames } = useStyles();  // 场景1:背景玻璃模糊效果(朦胧美学)  const blurModalStyles: ModalProps["styles"] = {    body: {      padding: 24,    },  };  // 场景2:渐变色背景模态框(无模糊效果)  const gradientModalStyles: ModalProps["styles"] = {    mask: {      backgroundImage: `linear-gradient(        135deg,         rgba(99, 102, 241, 0.8) 0%,         rgba(168, 85, 247, 0.6) 50%,         rgba(236, 72, 153, 0.8) 100%      )`,    },    body: {      padding: 24,    },    header: {      background: "linear-gradient(to right, #6366f1, #a855f7)",      color: "#fff",      borderBottom: "none",    },    footer: {      borderTop: "1px solid #e5e7eb",      textAlign: "center",    },  };  // 共享配置  const sharedProps: ModalProps = {    centered: true,    classNames,  };  return (    <div className="w-full h-[100vh] overflow-auto p-[24px] space-y-5">      <Card        title="Ant Design 6 模态框样式示例"        bordered={false}        extra={          <Text type="secondary" className="text-sm">            朦胧美学 + 渐变背景,高级感拉满!          </Text>        }      >        <Flex          gap="middle"          align="center"          justify="center"          style={{ padding: 40, minHeight: 300 }}        >          <Button            type="primary"            size="large"            onClick={() => setBlurModalOpen(true)}          >            🌫️ 背景玻璃模糊效果          </Button>          <Button size="large" onClick={() => setGradientModalOpen(true)}>            🎨 渐变色背景模态框          </Button>          {/* 模态框 1:背景玻璃模糊效果(朦胧美学) */}          <Modal            {...sharedProps}            title="背景玻璃模糊效果"            styles={blurModalStyles}            open={blurModalOpen}            onOk={() => setBlurModalOpen(false)}            onCancel={() => setBlurModalOpen(false)}            okText="太美了"            cancelText="关闭"            mask={{ enabled: true, blur: true }}            width={600}          >            {sharedContent}            <div              style={{                marginTop: 16,                padding: 16,                background: "rgba(255, 255, 255, 0.6)",                borderRadius: 8,                backdropFilter: "blur(10px)",              }}            >              <Text type="secondary">                <strong>💡 设计亮点:</strong>                启用了 mask=&#123;&#123; blur: true &#125;&#125;,                背景会自动应用模糊效果,营造出朦胧美学的高级质感。              </Text>            </div>          </Modal>          {/* 模态框 2:渐变色背景(无模糊效果) */}          <Modal            {...sharedProps}            title="渐变色背景模态框"            styles={gradientModalStyles}            open={gradientModalOpen}            onOk={() => setGradientModalOpen(false)}            onCancel={() => setGradientModalOpen(false)}            okText="好看"            cancelText="关闭"            mask={{ enabled: true, blur: false }}            width={600}          >            {sharedContent}            <div              style={{                marginTop: 16,                padding: 16,                background: "linear-gradient(135deg, #fef3c7 0%, #fce7f3 100%)",                borderRadius: 8,                border: "1px solid rgba(168, 85, 247, 0.2)",              }}            >              <Text type="secondary">                <strong>🎨 设计亮点:</strong>                通过 styles.mask 设置渐变背景色,同时 styles.header                应用了渐变头部,打造独特的视觉体验。              </Text>            </div>          </Modal>        </Flex>        <div className="mt-6 p-5 bg-gradient-to-r from-blue-50 to-purple-50 rounded-xl border border-purple-200">          <Title level={5} className="mb-3">            📚 技术要点          </Title>          <Space direction="vertical" size="small" className="w-full">            <Text>              • <strong>玻璃模糊:</strong>使用 mask=&#123;&#123; blur: true &#125;&#125; 启用原生模糊效果            </Text>            <Text>              • <strong>渐变背景:</strong>通过 styles.mask.backgroundImage 设置渐变色            </Text>            <Text>              • <strong>语义化定制:</strong>使用 styles.header/body/footer 精准控制各部分样式            </Text>            <Text>              • <strong>antd-style 集成:</strong>使用 createStyles 定义可复用的样式类名            </Text>          </Space>        </div>      </Card>    </div>  );};
复制代码




核心特性解析

1. 背景模糊开关


通过 mask 属性的 blur 配置项,可以一键开启/关闭背景模糊效果:


  • mask={{ enabled: true, blur: true }}:启用毛玻璃效果

  • mask={{ enabled: true, blur: false }}:使用传统半透明遮罩


2. 语义化样式定制


styles 属性允许精准控制组件各个部分的样式,无需编写复杂的 CSS 选择器:


  • styles.mask:遮罩层样式(可设置渐变背景)

  • styles.header:头部样式(可定制颜色、边框)

  • styles.body:内容区样式(可调整间距)

  • styles.footer:底部样式(可设置对齐方式)


3. antd-style 集成


结合 antd-style 可以创建主题感知的样式:


  • 访问 Design Token(如 token.borderRadiusLG)

  • 样式自动响应主题切换(亮色/暗色模式)

  • 通过 classNames 属性应用 CSS 类名

视觉效果对比

使用背景模糊和语义化样式定制后,Modal 的视觉呈现发生了显著变化:


1. 背景模糊效果: 遮罩层从单调的半透明黑色变为毛玻璃效果,背景内容呈现柔和的模糊感


2. 精准样式控制: 通过 styles.mask/header/body/footer 可以像搭积木一样组装出品牌化的对话框


3. 主题联动: 结合 antd-style 后,样式会自动响应全局主题切换,无需手动维护暗色模式样式


4. 维护性提升: 告别 .ant-modal .ant-modal-content .ant-modal-header 这样的深层选择器,样式意图清晰明确


这种设计让 Ant Design 6.0 的组件定制从"CSS 覆盖战争"升级为"API 声明式配置",显著降低了样式维护成本,同时保持了高度的灵活性。

七、Card 赛博朋克风格:霓虹科技美学的呈现

在传统的企业级应用中,卡片组件往往采用简洁素雅的设计。但对于游戏、科技、创意类产品,开发者往往需要更具视觉冲击力的效果。Ant Design 6.0 的 Card 组件配合 antd-style,可以轻松实现赛博朋克风格的霓虹发光边框、深色内阴影和动态动画效果,让你的界面充满未来感和科技感。

赛博朋克卡片实现

以下示例展示了如何使用 antd-style 的 CSS-in-JS 能力,为 Card 组件打造完整的赛博朋克视觉风格:


import { Card, Typography, Button, Space, Avatar, Row, Col } from "antd";import { createStyles } from "antd-style";import {  ThunderboltOutlined,  RocketOutlined,  FireOutlined,  StarOutlined,  TrophyOutlined,} from "@ant-design/icons";const { Title, Text, Paragraph } = Typography;// 使用 antd-style 创建赛博朋克风格样式const useStyles = createStyles(({ css }) => ({  // 赛博朋克卡片 - 紫色霓虹  cyberpunkCard: css`    background: rgba(15, 15, 35, 0.9);    border: 2px solid #a855f7;    border-radius: 16px;    overflow: hidden;    position: relative;    transition: all 0.3s ease;    /* 发光边框效果 */    box-shadow: 0 0 20px rgba(168, 85, 247, 0.5),      inset 0 0 20px rgba(168, 85, 247, 0.1);    &:hover {      transform: translateY(-5px);      box-shadow: 0 0 30px rgba(168, 85, 247, 0.8),        inset 0 0 30px rgba(168, 85, 247, 0.2);      border-color: #c084fc;    }    /* 顶部霓虹灯条 */    &::before {      content: "";      position: absolute;      top: 0;      left: 0;      right: 0;      height: 3px;      background: linear-gradient(        90deg,        transparent,        #a855f7,        #c084fc,        #a855f7,        transparent      );      animation: neonFlow 3s ease-in-out infinite;    }    @keyframes neonFlow {      0%, 100% { opacity: 1; }      50% { opacity: 0.5; }    }  `,  // 霓虹文字  neonText: css`    color: #fff;    text-shadow: 0 0 10px currentColor,                 0 0 20px currentColor,                 0 0 30px currentColor;    font-weight: bold;  `,  // 霓虹按钮  neonButton: css`    background: transparent !important;    border: 2px solid currentColor !important;    color: inherit !important;    text-shadow: 0 0 10px currentColor;    box-shadow: 0 0 10px currentColor,                inset 0 0 10px rgba(255, 255, 255, 0.1);    transition: all 0.3s ease !important;    &:hover {      transform: scale(1.05);      box-shadow: 0 0 20px currentColor,                  inset 0 0 20px rgba(255, 255, 255, 0.2) !important;    }  `,  // 数据面板  dataPanel: css`    background: rgba(0, 0, 0, 0.3);    border: 1px solid rgba(255, 255, 255, 0.1);    border-radius: 8px;    padding: 16px;    backdrop-filter: blur(10px);  `,}));export default () => {  const { styles } = useStyles();  return (    <Row gutter={[24, 24]}>      <Col span={8}>        <Card          className={styles.cyberpunkCard}          hoverable          styles={{ body: { padding: 24 } }}        >          <div style={{ position: "relative", zIndex: 1 }}>            {/* 头部 */}            <div style={{ display: "flex", alignItems: "center", marginBottom: 16 }}>              <Avatar                size={64}                icon={<ThunderboltOutlined />}                style={{                  background: "linear-gradient(135deg, #a855f7, transparent)",                  border: "2px solid #a855f7",                  color: "#a855f7",                  filter: "drop-shadow(0 0 10px #a855f7)",                }}              />            </div>            {/* 标题 */}            <Title level={4} className={styles.neonText} style={{ color: "#a855f7" }}>              QUANTUM PROCESSOR            </Title>            <Text style={{ color: "#888", display: "block", marginBottom: 16 }}>              量子处理器            </Text>            {/* 描述 */}            <Paragraph style={{ color: "#bbb", marginBottom: 20 }}>              第九代量子处理器,采用纳米级光刻技术,配备AI神经网络加速引擎。            </Paragraph>            {/* 数据面板 */}            <div className={styles.dataPanel} style={{ marginBottom: 20 }}>              <Space direction="vertical" style={{ width: "100%" }} size={12}>                <div style={{ display: "flex", justifyContent: "space-between" }}>                  <Text style={{ color: "#888" }}>处理速度</Text>                  <Text strong style={{ color: "#a855f7" }}>5.2 PHz</Text>                </div>                <div style={{ display: "flex", justifyContent: "space-between" }}>                  <Text style={{ color: "#888" }}>核心数量</Text>                  <Text strong style={{ color: "#a855f7" }}>128 核</Text>                </div>              </Space>            </div>            {/* 能量条 */}            <div style={{ marginBottom: 20 }}>              <div style={{ display: "flex", justifyContent: "space-between", marginBottom: 8 }}>                <Text style={{ color: "#888", fontSize: 12 }}>POWER LEVEL</Text>                <Text strong style={{ color: "#a855f7", fontSize: 12 }}>9999</Text>              </div>              <div style={{                height: 6,                background: "rgba(0, 0, 0, 0.3)",                borderRadius: 3,                overflow: "hidden",                border: "1px solid rgba(255, 255, 255, 0.1)",              }}>                <div style={{                  height: "100%",                  width: "92%",                  background: "linear-gradient(90deg, #a855f7, transparent)",                  boxShadow: "0 0 10px #a855f7",                }} />              </div>            </div>            {/* 操作按钮 */}            <Space style={{ width: "100%" }}>              <Button                type="primary"                className={styles.neonButton}                style={{ color: "#a855f7", flex: 1 }}                icon={<StarOutlined />}              >                激活              </Button>              <Button                className={styles.neonButton}                style={{ color: "#a855f7" }}                icon={<TrophyOutlined />}              >                详情              </Button>            </Space>          </div>        </Card>      </Col>    </Row>  );};
复制代码



核心技术要点

1. 霓虹发光边框


通过多层 box-shadow 实现外发光和内阴影的叠加效果:


box-shadow:   0 0 20px rgba(168, 85, 247, 0.5),        /* 外发光 */  inset 0 0 20px rgba(168, 85, 247, 0.1);  /* 内阴影 */
复制代码


2. 动态霓虹灯条


使用伪元素和渐变动画创建流动的霓虹灯效果:


&::before {  content: "";  background: linear-gradient(90deg, transparent, #a855f7, transparent);  animation: neonFlow 3s ease-in-out infinite;}
复制代码


3. 霓虹文字效果


通过 text-shadow 的多层叠加模拟霓虹灯文字:


text-shadow:   0 0 10px currentColor,  0 0 20px currentColor,  0 0 30px currentColor;
复制代码


4. 毛玻璃数据面板


结合半透明背景和 backdrop-filter 实现毛玻璃效果:


background: rgba(0, 0, 0, 0.3);backdrop-filter: blur(10px);
复制代码


5. 交互动画


hover 时同步触发多个动画效果:


  • 卡片上浮:transform: translateY(-5px)

  • 发光增强:box-shadow 强度提升

  • 边框颜色变化:border-color 过渡

样式定制优势

使用 Ant Design 6.0 + antd-style 实现赛博朋克风格的优势:


1. CSS-in-JS 强大能力: 支持嵌套、伪元素、动画等高级特性,无需额外 CSS 文件


2. 类型安全: TypeScript 提供完整的类型提示,减少样式错误


3. 动态主题: 可以轻松切换不同颜色的霓虹主题(紫色、青色、粉色等)


4. 组件封装: 样式与组件逻辑共存,便于复用和维护


5. 性能优化: antd-style 自动处理样式注入和缓存,性能优秀


这种设计风格通过强烈的视觉冲击力和独特的科技感,能够有效吸引用户注意力,提升品牌记忆度,特别适合面向年轻用户群体的产品。

八、升级建议与实践策略

对于考虑升级到 Ant Design 6.0 的团队,建议采取以下策略:


1.渐进式升级路径


  1. 新项目直接使用:全新项目建议直接使用 6.0 版本,享受所有新特性

  2. 现有项目评估:评估项目依赖和定制程度,制定分阶段升级计划

  3. 组件逐步替换:可以先替换使用新功能的组件,再逐步迁移其他部分


2.兼容性注意事项


  1. 检查废弃 API:Ant Design 6.0 移除了之前版本已标记为废弃的 API

  2. 样式覆盖检查:如果项目中有深度定制样式,需要检查与新版本的兼容性

  3. 测试核心流程:升级后重点测试表单提交、数据展示等核心用户流程

九、总结

Ant Design 6.0 的组件功能更新聚焦于解决实际开发中的痛点,通过引入 Masonry 瀑布流布局、Tooltip 平滑移动、InputNumber 拨轮模式、Drawer 拖拽调整、Modal 背景模糊以及 Card 深度定制等特性,显著提升了开发效率和用户体验。


这些更新体现了现代前端设计的几个核心趋势:


1. 交互流畅性: 如 Tooltip 的平滑过渡,减少界面跳跃感


2. 设备适配性: 如 InputNumber 的触摸友好设计


3. 布局灵活性: 如 Masonry 的动态布局和 Drawer 的可调整尺寸


4. 视觉现代化: 如 Modal 的背景模糊效果,营造朦胧美学的高级质感


5. 样式可控性: 通过 classNamesstyles API 实现精准的组件定制


6. 风格多样性: 结合 antd-style 可实现从企业风到赛博朋克等多样化视觉风格


特别是与 antd-style 的深度集成,让开发者能够充分发挥 CSS-in-JS 的强大能力,从简洁的企业级设计到炫酷的赛博朋克风格,都能轻松实现。这些改进让 Ant Design 6.0 不仅保持了企业级应用的稳定性和专业性,还增加了更多现代化、人性化的交互细节和视觉创意空间,是构建下一代 Web 应用的理想选择。

往期回顾

1.Java 设计模式:原理、框架应用与实战全解析|得物技术


2.Go 语言在高并发高可用系统中的实践与解决方案|得物技术


3.从 0 到 1 搭建一个智能分析 OBS 埋点数据的 AI Agent|得物技术


4.数据库 AI 方向探索-MCP 原理解析 &DB 方向实战|得物技术


5.项目性能优化实践:深入 FMP 算法原理探索|得物技术

文 /三七

关注得物技术,每周更新技术干货


要是觉得文章对你有帮助的话,欢迎评论转发点赞~


未经得物技术许可严禁转载,否则依法追究法律责任。

发布于: 刚刚阅读数: 3
用户头像

得物技术

关注

得物APP技术部 2019-11-13 加入

关注微信公众号「得物技术」

评论

发布
暂无评论
Ant Design 6.0 尝鲜:上手现代化组件开发|得物技术_前端_得物技术_InfoQ写作社区