react-xudy-ui
v1.0.5
Published
React 19 compatible global UI helpers: Message, Notification, Modal (AntD-like APIs)
Downloads
29
Readme
react-xudy-ui
为 React 18/19 提供与 Ant Design 相似的全局 UI 能力(Message、Notification、Modal),完全兼容 React 19(内部使用 react-dom/client 的 createRoot,不依赖已废弃的 ReactDOM.render)。
主要功能
- Message:全局轻提示(info/success/warning/error/loading),支持默认图标和自定义图标
- Notification:全局通知(支持四角定位,包含标题与描述)
- Modal:组件形式 + Confirm API(支持动画效果、自定义宽度)
- 完全兼容 React 19:使用
createRoot替代ReactDOM.render - TypeScript 支持:完整的类型定义,开发更安全
- 轻量级:无第三方依赖,专注于核心功能
安装
基础安装
npm install react-xudy-ui或使用 yarn:
yarn add react-xudy-ui类型支持(TypeScript 项目)
确保你的项目已安装 React 类型定义:
npm install --save-dev @types/react @types/react-dom兼容性
- React 18.x
- React 19.x
- 支持现代浏览器(Chrome, Firefox, Safari, Edge)
快速开始
基础用法
import React, { useState } from "react";
import { message, notification, Modal, confirm } from "react-xudy-ui";
function App() {
const [modalVisible, setModalVisible] = useState(false);
return (
<div className="demo-container">
<h1>React Xudy UI 示例</h1>
<h2>Message 示例</h2>
<button onClick={() => message.success("操作成功")}>成功提示</button>
<button onClick={() => message.error("操作失败")}>错误提示</button>
<button onClick={() => message.warning("警告信息")}>警告提示</button>
<button onClick={() => message.info("普通提示")}>信息提示</button>
<button onClick={() => message.loading("加载中...")}>加载提示</button>
<h2>Notification 示例</h2>
<button onClick={() => {
notification.open({
message: "新消息",
description: "这是一条通知内容描述,支持多行显示。",
placement: "topRight"
});
}}>打开通知</button>
<h2>Modal 组件示例</h2>
<button onClick={() => setModalVisible(true)}>打开模态框</button>
<Modal
open={modalVisible}
title="模态框标题"
onOk={() => {
setModalVisible(false);
message.success("已确认");
}}
onCancel={() => setModalVisible(false)}
centered
width={500}
>
<p>这是模态框的内容区域,支持任何 ReactNode。</p>
<p>模态框现在支持动画效果和自定义宽度!</p>
</Modal>
<h2>Confirm API 示例</h2>
<button onClick={() => {
confirm({
title: "确认操作",
content: "确定要执行此操作吗?",
onOk: () => message.success("操作已执行"),
onCancel: () => message.info("已取消操作")
});
}}>打开确认框</button>
</div>
);
}
export default App;Message 全局提示
全局轻提示,自动关闭,支持不同类型与默认图标,方便用户快速了解操作反馈。
最新特性
- 默认图标:每种消息类型都有对应的默认图标(info: i, success: ✓, warning: !, error: ✗, loading: ⟳)
- 可定制图标:支持自定义图标组件或内容
- 图标显示控制:可通过
showIcon属性控制是否显示图标 - loading 动画:loading 类型的图标带有自动旋转动画
API 列表
message.open(config: MessageConfig):打开消息,支持完整配置message.info(content: ReactNode, duration?: number, onClose?: () => void):信息提示message.success(content: ReactNode, duration?: number, onClose?: () => void):成功提示message.warning(content: ReactNode, duration?: number, onClose?: () => void):警告提示message.error(content: ReactNode, duration?: number, onClose?: () => void):错误提示message.loading(content: ReactNode, duration?: number, onClose?: () => void):加载提示message.destroy(key?: React.Key):关闭指定或全部消息message.config(globalConfig: MessageGlobalConfig):设置全局配置
类型定义
// 消息类型
type MessageType = "info" | "success" | "warning" | "error" | "loading";
// 单个消息配置
interface MessageConfig {
// 消息内容
content: React.ReactNode;
// 消息类型
type?: MessageType;
// 显示时长(秒),默认 3 秒
duration?: number;
// 唯一标识,用于后续操作(如关闭)
key?: React.Key;
// 消息关闭回调
onClose?: () => void;
// 自定义图标
icon?: React.ReactNode;
// 是否显示图标,默认 true
showIcon?: boolean;
}
// 全局配置
interface MessageGlobalConfig {
// 默认显示时长(秒)
duration?: number;
// 最大同时显示数量
maxCount?: number;
// 顶部偏移量(像素)
top?: number;
// 自定义容器获取函数
getContainer?: () => HTMLElement;
}详细示例
1. 基本使用(快捷方法)
// 基本使用 - 成功提示,默认 3 秒自动关闭
message.success("保存成功");
// 自定义显示时长(2 秒)
message.error("操作失败", 2);
// 添加关闭回调
message.warning("请检查表单", 3, () => {
console.log("警告消息已关闭");
});
// 使用 ReactNode 作为内容
message.info(
<div>
<span>欢迎回来,</span>
<strong>张三</strong>
</div>
);2. 完整配置(open 方法)
// 完全自定义消息
message.open({
content: "自定义消息内容",
type: "warning",
duration: 5,
key: "custom_msg",
onClose: () => console.log("自定义消息已关闭"),
// 自定义图标
icon: <span style={{ color: "#faad14" }}>⚠️</span>
});3. 图标控制
// 默认显示图标
message.success("操作成功");
// 禁用图标显示
message.open({
content: "无图标的消息",
type: "info",
showIcon: false
});
// 使用自定义 React 组件作为图标
import { MyCustomIcon } from './icons';
message.open({
content: "使用自定义组件图标",
type: "success",
icon: <MyCustomIcon size={20} />
});4. 关闭控制
// 打开消息并保存返回值
const { close } = message.loading("正在处理中,请稍候...");
// 处理完成后手动关闭
setTimeout(() => {
close();
message.success("处理完成");
}, 3000);
// 根据 key 关闭指定消息
message.open({ key: "msg1", content: "测试消息" });
message.destroy("msg1");
// 关闭所有消息
message.destroy();5. 全局配置
// 在应用初始化时配置全局默认值
message.config({
duration: 4, // 默认 4 秒
maxCount: 3, // 最多同时显示 3 条
top: 60, // 距离顶部 60px
getContainer: () => document.getElementById("message-container") || document.body
});Notification 全局通知
全局通知组件,提供更详细的信息展示,支持不同位置放置。
API 列表
notification.open(args: NotificationArgs):打开通知notification.close(key: React.Key):关闭指定通知notification.destroy():关闭所有通知notification.config(globalConfig: NotificationGlobalConfig):设置全局配置
类型定义
// 通知位置
type Placement = "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
// 通知配置
interface NotificationArgs {
// 通知标题
message: React.ReactNode;
// 通知描述内容
description?: React.ReactNode;
// 自定义图标
icon?: React.ReactNode;
// 显示时长(秒)
duration?: number;
// 唯一标识
key?: React.Key;
// 显示位置
placement?: Placement;
// 关闭回调
onClose?: () => void;
}
// 全局配置
interface NotificationGlobalConfig {
// 默认位置
placement?: Placement;
// 顶部偏移量(像素)
top?: number;
// 底部偏移量(像素)
bottom?: number;
// 默认显示时长(秒)
duration?: number;
// 自定义容器获取函数
getContainer?: () => HTMLElement;
}详细示例
1. 基本使用
// 基本通知
notification.open({
message: "系统通知",
description: "这是一条系统通知的详细描述,支持多行文本展示。"
});
// 自定义时长
notification.open({
message: "临时提醒",
description: "这条通知将在 2 秒后自动关闭",
duration: 2
});2. 位置控制
// 不同位置的通知
notification.open({
message: "顶部左侧",
description: "显示在页面的左上角",
placement: "topLeft"
});
notification.open({
message: "底部右侧",
description: "显示在页面的右下角",
placement: "bottomRight"
});
// 全局默认位置配置
notification.config({
placement: "bottomRight",
top: 24,
bottom: 24
});3. 自定义内容与图标
// 使用 ReactNode 作为标题和描述
notification.open({
message: <span>🎉 <strong>活动通知</strong></span>,
description: (
<div>
<p>新的促销活动已开始!</p>
<button onClick={(e) => {
e.stopPropagation();
console.log("查看详情");
}}>查看详情</button>
</div>
),
icon: <span>🔔</span>
});4. 关闭控制
// 保存 key 以便后续操作
notification.open({
key: "noti1",
message: "可关闭的通知",
description: "可以通过 key 手动关闭"
});
// 关闭指定通知
notification.close("noti1");
// 关闭所有通知
notification.destroy();Modal 模态框组件
受控的对话框组件,用于重要操作的确认、信息展示等场景。
最新特性
- 动画效果:添加了淡入淡出和位移动画,提升用户体验
- 自定义宽度:支持通过
width属性自定义模态框宽度 - 完全受控:基于
openprop 完全受控的组件设计
Props 列表
interface ModalProps {
// 是否显示模态框(受控属性)
open?: boolean;
// 模态框标题
title?: React.ReactNode;
// 模态框内容
children?: React.ReactNode;
// 点击确定按钮的回调
onOk?: () => void;
// 点击取消按钮或遮罩关闭的回调
onCancel?: () => void;
// 确定按钮文字
okText?: React.ReactNode;
// 取消按钮文字
cancelText?: React.ReactNode;
// 底部按钮区域,设置为 null 则隐藏
footer?: React.ReactNode | null;
// 是否居中显示
centered?: boolean;
// 点击遮罩是否可以关闭
maskClosable?: boolean;
// 关闭时是否销毁内容
destroyOnClose?: boolean;
// 自定义宽度,支持数字(像素)或字符串
width?: string | number;
}详细示例
1. 基本使用
import { useState } from 'react';
import { Modal } from 'react-xudy-ui';
function Demo() {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)}>打开模态框</button>
<Modal
open={open}
title="基本模态框"
onOk={() => {
console.log('确认');
setOpen(false);
}}
onCancel={() => {
console.log('取消');
setOpen(false);
}}
>
<p>这是模态框的内容区域。</p>
<p>支持任何 ReactNode 作为内容。</p>
</Modal>
</>
);
}2. 自定义宽度
// 数字类型(像素)
<Modal
open={open}
title="自定义宽度 (像素)"
width={600}
onOk={() => setOpen(false)}
onCancel={() => setOpen(false)}
>
宽度为 600px 的模态框
</Modal>
// 字符串类型
<Modal
open={open}
title="自定义宽度 (百分比)"
width="80%"
onOk={() => setOpen(false)}
onCancel={() => setOpen(false)}
>
宽度为视口宽度 80% 的模态框
</Modal>3. 居中显示
<Modal
open={open}
title="居中模态框"
centered
onOk={() => setOpen(false)}
onCancel={() => setOpen(false)}
>
<p>这个模态框在屏幕上垂直居中显示。</p>
</Modal>4. 自定义底部
// 隐藏底部
<Modal
open={open}
title="无底部按钮"
footer={null}
onCancel={() => setOpen(false)}
>
<p>这个模态框没有底部按钮区域。</p>
</Modal>
// 自定义底部按钮
<Modal
open={open}
title="自定义底部"
footer={
<div style={{ display: 'flex', gap: '8px', justifyContent: 'flex-end' }}>
<button onClick={() => setOpen(false)}>返回</button>
<button onClick={() => {
console.log('保存草稿');
setOpen(false);
}}>保存草稿</button>
<button
style={{ backgroundColor: '#1677ff', color: 'white' }}
onClick={() => {
console.log('提交');
setOpen(false);
}}
>
提交
</button>
</div>
}
onCancel={() => setOpen(false)}
>
<p>自定义底部按钮区域。</p>
</Modal>5. 遮罩关闭控制
// 禁止点击遮罩关闭
<Modal
open={open}
title="不可通过遮罩关闭"
maskClosable={false}
onOk={() => setOpen(false)}
onCancel={() => setOpen(false)}
>
<p>点击遮罩层不会关闭此模态框。</p>
</Modal>6. 内容销毁控制
// 关闭时销毁内容(组件卸载)
<Modal
open={open}
title="销毁内容"
destroyOnClose
onOk={() => setOpen(false)}
onCancel={() => setOpen(false)}
>
<p>当模态框关闭时,此内容将被完全销毁。</p>
<p>再次打开时会重新渲染。</p>
</Modal>Confirm API 确认对话框
全局确认对话框,用于需要用户确认的重要操作。
最新特性
- 支持宽度定制:可通过
width属性自定义对话框宽度 - 动态更新:支持通过
update方法动态更新对话框内容
API 列表
confirm(args: ConfirmArgs):打开确认对话框info(args: ConfirmArgs):打开信息确认对话框success(args: ConfirmArgs):打开成功确认对话框error(args: ConfirmArgs):打开错误确认对话框warning(args: ConfirmArgs):打开警告确认对话框
类型定义
interface ConfirmArgs {
// 标题
title?: React.ReactNode;
// 内容
content?: React.ReactNode;
// 确定按钮文字
okText?: React.ReactNode;
// 取消按钮文字
cancelText?: React.ReactNode;
// 点击确定回调
onOk?: () => void;
// 点击取消回调
onCancel?: () => void;
// 是否居中
centered?: boolean;
// 自定义图标
icon?: React.ReactNode;
// 自定义宽度
width?: string | number;
}返回值
所有确认对话框方法都返回一个对象,包含以下方法:
interface ConfirmResult {
// 关闭对话框
close: () => void;
// 更新对话框内容
update: (nextArgs: Partial<ConfirmArgs>) => void;
}详细示例
1. 基本使用
// 基本确认框
confirm({
title: "确认删除",
content: "确定要删除这条数据吗?删除后不可恢复。",
onOk: () => {
console.log("删除操作");
message.success("删除成功");
},
onCancel: () => {
console.log("取消删除");
}
});
// 快捷方法
info({ title: "提示", content: "这是一条提示信息" });
success({ title: "成功", content: "操作已完成" });
error({ title: "错误", content: "操作失败,请重试" });
warning({ title: "警告", content: "操作可能导致数据丢失" });2. 自定义按钮文字
confirm({
title: "危险操作",
content: "此操作将删除所有数据,确定要继续吗?",
okText: "删除",
cancelText: "返回",
onOk: () => console.log("执行删除"),
onCancel: () => console.log("取消操作")
});3. 动态更新
// 保存对话框引用
const confirmRef = confirm({
title: "处理中",
content: "正在准备数据...",
onOk: () => console.log("确认"),
onCancel: () => console.log("取消"),
icon: <span>⏳</span>
});
// 模拟数据加载后更新对话框
setTimeout(() => {
confirmRef.update({
title: "数据已准备",
content: "数据处理完成,可以继续操作",
icon: <span>✅</span>
});
}, 2000);4. 自定义宽度
confirm({
title: "宽确认框",
content: "这是一个宽度自定义的确认对话框,可以容纳更多内容。",
width: 600,
onOk: () => console.log("确认"),
onCancel: () => console.log("取消")
});
// 使用百分比
confirm({
title: "响应式确认框",
content: "宽度为视口宽度的 70%",
width: "70%",
onOk: () => console.log("确认")
});5. 主动关闭
const confirmRef = confirm({
title: "自动关闭",
content: "5秒后将自动关闭",
onOk: () => console.log("确认"),
onCancel: () => console.log("取消")
});
// 5秒后自动关闭
setTimeout(() => {
confirmRef.close();
}, 5000);进阶使用指南
1. 样式自定义
所有组件都提供了基础样式,可以通过覆盖相应的 CSS 类来自定义样式:
Message 样式类
/* 消息包装器 */
.xudy-message-wrapper { /* 自定义样式 */ }
/* 消息列表容器 */
.xudy-message-list { /* 自定义样式 */ }
/* 单个消息 */
.xudy-message { /* 自定义样式 */ }
/* 消息类型样式 */
.xudy-message-info { /* 信息类型样式 */ }
.xudy-message-success { /* 成功类型样式 */ }
.xudy-message-warning { /* 警告类型样式 */ }
.xudy-message-error { /* 错误类型样式 */ }
.xudy-message-loading { /* 加载类型样式 */ }
/* 图标容器 */
.xudy-message-icon { /* 图标样式 */ }Notification 样式类
/* 通知包装器 */
.xudy-noti-wrapper { /* 自定义样式 */ }
/* 单个通知 */
.xudy-noti { /* 自定义样式 */ }
/* 通知标题 */
.xudy-noti-title { /* 标题样式 */ }
/* 通知描述 */
.xudy-noti-desc { /* 描述样式 */ }
/* 通知图标 */
.xudy-noti-icon { /* 图标样式 */ }Modal 样式类
/* 遮罩层 */
.xudy-modal-mask { /* 自定义样式 */ }
/* 模态框容器 */
.xudy-modal-wrap { /* 自定义样式 */ }
/* 模态框主体 */
.xudy-modal { /* 自定义样式 */ }
/* 模态框头部 */
.xudy-modal-header { /* 头部样式 */ }
/* 模态框内容 */
.xudy-modal-body { /* 内容样式 */ }
/* 模态框底部 */
.xudy-modal-footer { /* 底部样式 */ }
/* 按钮样式 */
.xudy-btn { /* 按钮基础样式 */ }
.xudy-btn-primary { /* 主按钮样式 */ }2. 自定义容器
所有组件都支持通过 getContainer 配置自定义渲染容器:
// 为 Message 配置自定义容器
message.config({
getContainer: () => {
let container = document.getElementById('message-container');
if (!container) {
container = document.createElement('div');
container.id = 'message-container';
container.style.position = 'relative';
document.body.appendChild(container);
}
return container;
}
});
// 为 Notification 配置自定义容器
notification.config({
getContainer: () => document.getElementById('notification-container') || document.body
});3. React 19 兼容性说明
本库完全兼容 React 19,主要是因为:
- 使用
react-dom/client的createRoot替代已废弃的ReactDOM.render - 所有组件使用最新的 React Hooks API
- 避免使用任何在 React 19 中已废弃的 API
常见问题与解决方案
1. TypeScript 报错:找不到模块 "react-dom" 的声明文件
解决方案:安装 React 类型定义
npm install --save-dev @types/react @types/react-dom2. 消息或通知无法显示
可能原因:
- 自定义容器不存在
- 容器样式问题导致不可见
解决方案:
// 检查容器是否正确设置
message.config({
getContainer: () => document.body // 使用默认容器
});3. 组件样式与项目样式冲突
解决方案:
- 使用 CSS Modules 或 styled-components 隔离样式
- 通过覆盖组件的 CSS 类来调整样式
- 增加选择器的优先级以确保样式正确应用
4. 模态框宽度设置无效
解决方案:
- 确保
width属性值正确(数字或有效的 CSS 字符串) - 检查是否有 CSS 覆盖了设置的宽度
// 正确使用方法
<Modal width={600} ... />
<Modal width="80%" ... />开发与构建
项目结构
src/
├── index.ts # 主入口文件
├── message/ # Message 组件
│ └── index.tsx
├── notification/ # Notification 组件
│ └── index.tsx
├── modal/ # Modal 组件
│ ├── Modal.tsx
│ ├── confirmApi.tsx
│ └── index.ts
└── utils/ # 工具函数
├── injectStyles.ts
└── singletonRoot.ts构建项目
# 安装依赖
npm install
# 构建项目
npm run build
# 构建产物位置: dist/发布到 npm
# 确保已登录 npm
npm login
# 发布版本
npm publish变更日志
v1.0.0
- 实现基础功能与 React 19 兼容
- 支持 Message、Notification、Modal + Confirm API
v1.1.0
- Modal 组件添加动画效果
- Modal 组件添加 width 属性支持
- Message 组件添加默认图标
未来规划
- 动画过渡效果增强
- 更多默认图标选择
- Promise 化的 Confirm API
- 主题定制能力
- 无障碍访问(a11y)优化
License
ISC
notification.open(args)
notification.open({
message: "系统提示",
description: "您的会话即将过期,请保存数据。",
icon: <span>🔔</span>,
duration: 6,
key: "noti_1", // 可用于关闭
placement: "topRight",
onClose: () => console.log("notification closed"),
});- 不同
placement效果
notification.open({ message: "左上", placement: "topLeft" });
notification.open({ message: "右下", placement: "bottomRight" });notification.close(key)与notification.destroy()
notification.close("noti_1"); // 关闭指定
notification.destroy(); // 关闭全部notification.config(globalConfig)
notification.config({
placement: "bottomRight",
top: 24,
bottom: 32,
duration: 3.5,
getContainer: () => document.body,
});Modal(组件)
受控的对话框组件,支持标题、底部按钮、居中、遮罩关闭、销毁内容等。
Props 概览
interface ModalProps {
open?: boolean;
title?: React.ReactNode;
children?: React.ReactNode;
onOk?: () => void;
onCancel?: () => void;
okText?: React.ReactNode; // 默认 “确定”
cancelText?: React.ReactNode; // 默认 “取消”
footer?: React.ReactNode | null; // 设置为 null 隐藏底部
centered?: boolean;
maskClosable?: boolean; // 默认 true
destroyOnClose?: boolean;
}每个属性示例
open控制显示与隐藏
const [open, setOpen] = useState(false);
<Modal open={open} onCancel={() => setOpen(false)} />title标题
<Modal open title={<span>删除确认 <b>Danger</b></span>} />children内容
<Modal open>
<p>这是内容段落</p>
<div>支持任何 ReactNode</div>
</Modal>onOk与onCancel
<Modal
open
onOk={() => console.log("ok")}
onCancel={() => console.log("cancel")}
/>okText与cancelText
<Modal open okText="提交" cancelText="返回" />- 自定义
footer(传null隐藏底部;传节点自定义)
// 隐藏底部
<Modal open footer={null} />
// 自定义底部
<Modal
open
footer={
<div style={{ display: "flex", gap: 8, justifyContent: "flex-end" }}>
<button onClick={() => console.log("自定义取消")}>自定义取消</button>
<button onClick={() => console.log("自定义确定")}>自定义确定</button>
</div>
}
/>centered居中
<Modal open centered title="居中对话框">内容</Modal>maskClosable点击遮罩关闭(默认 true)
<Modal open maskClosable={false} title="不可通过遮罩关闭">内容</Modal>destroyOnClose关闭后销毁内容节点
<Modal open destroyOnClose title="销毁内容">内容</Modal>Confirm API(全局确认框)
无需在页面布置组件,直接调用生成确认框。支持更新与关闭。
API 概览
confirm(args)info(args)success(args)error(args)warning(args)- 返回值:
{ close: () => void; update: (next: Partial<ConfirmArgs>) => void }
类型定义(参考)
interface ConfirmArgs {
title?: React.ReactNode;
content?: React.ReactNode;
okText?: React.ReactNode;
cancelText?: React.ReactNode;
onOk?: () => void;
onCancel?: () => void;
centered?: boolean;
icon?: React.ReactNode;
}示例
- 基本用法
const h = confirm({
title: "确认删除",
content: "删除后不可恢复,是否继续?",
okText: "删除",
cancelText: "取消",
onOk: () => message.success("已删除"),
onCancel: () => message.info("已取消"),
centered: true,
icon: <span style={{ color: "#ff4d4f" }}>🗑️</span>,
});
// 主动更新文案或图标
setTimeout(() => {
h.update({
content: "请再次确认,当前操作非常重要!",
icon: <span style={{ color: "#faad14" }}>⚠️</span>,
});
}, 1000);
// 主动关闭
setTimeout(() => {
h.close();
}, 2000);- 快捷方法(
info/success/error/warning)
info({ title: "提示", content: "这是一条提示信息" });
success({ title: "成功", content: "操作成功" });
error({ title: "错误", content: "出现了问题" });
warning({ title: "警告", content: "请谨慎操作" });进阶与注意事项
React 19 兼容
- 内部所有全局渲染均通过
createRoot实现,不使用ReactDOM.render。 - 全局容器为单例,首次调用时创建,后续复用。
- 内部所有全局渲染均通过
容器与样式
- 默认渲染到
document.body,可通过各模块.config({ getContainer })指定容器。 - 基础样式通过注入
<style>提供(injectStylesOnce),如需自定义可以覆盖选择器:- Message 类名前缀:
xudy-message-* - Notification 类名前缀:
xudy-noti-* - Modal 类名前缀:
xudy-modal-*
- Message 类名前缀:
- 默认渲染到
TypeScript
- 如遇到
TS7016(找不到react-dom类型声明),安装@types/react和@types/react-dom。 - 所有
key默认生成字符串(兼容React.Key的string | number)。
- 如遇到
变更日志与规划
- v1:实现基础功能与 React 19 兼容(Message、Notification、Modal + Confirm API)。
- 规划:动画过渡、更多默认图标、Promise 化 Confirm、样式主题化。
License
ISC
