UNPKG

@ahmiao666/ahmiao-react-dialog-element

Version:
241 lines (186 loc) 6.06 kB
# 🎉 ahmiao React18 Dialog 高性能React18 Dialog组件,支持完整的性能控制和诊断功能。 ## 🚀 安装 ```bash npm install @ahmiao666/ahmiao-react-dialog-element ``` ## 📖 快速开始 ```tsx # amDialogCustom 弹窗组件使用说明 仅支持React18+ 因为底层订阅使用了 useSyncExternalStore ## 基本使用 ### 使用之前需要先把提供者组件 DialogCustomProvider 挂在到 app 里 ```tsx // 在应用根组件中挂载一次 import { DialogCustomProvider } from '@ahmiao666/ahmiao-react-dialog-element' import '@ahmiao666/ahmiao-react-dialog-element/index.css' function AppRoot() { return ( <> {/* 你的 App */} <DialogCustomProvider /> </> ) } ``` ```tsx import { DialogCustomStaticMethods } from '@ahmiao666/ahmiao-react-dialog-element' // 方式1: await 方式 const result = await DialogCustomStaticMethods.open( ({ onClose }) => ( <div> <p>确定要删除吗?</p> <button onClick={() => onClose(true)}>确定</button> <button onClick={() => onClose(false)}>取消</button> </div> ), { title: "确认删除", width: 400 } ) if (result) { console.log('用户确认删除') } // 方式2: .then() 方式 DialogCustomStaticMethods.open( ({ onClose }) => ( <div> <p>确定要删除吗?</p> <button onClick={() => onClose(true)}>确定</button> <button onClick={() => onClose(false)}>取消</button> </div> ), { title: "确认删除", width: 400 } ).then(result => { if (result) { console.log('用户确认删除') } }).catch(() => { console.log('弹窗被取消') }) ``` ## 配置选项 ```tsx DialogCustomStaticMethods.open(Component, { title: '弹窗标题', // 标题文本 width: 500, // 宽度:number=vw,string=任意CSS宽度 showIcon: true, // 是否显示标题图标 showClose: true, // 是否显示关闭按钮 icon: '📣', // 自定义标题图标(可选) maskClosable: true, // 点击遮罩是否可关闭 maskBg: 'rgba(0,0,0,0.6)', // 遮罩背景色(仅颜色) familyName: 'settings', // 弹窗命名空间(用于多弹窗并存) onNext: (v) => {}, // 可选的下一步回调(会传给内容组件) props: { data: '数据' } // 传递给内容组件的自定义 props }) ``` ### 遮罩与样式 - 仅支持通过 `maskBg` 修改遮罩颜色,默认值:`rgba(0, 0, 0, 0.4)`。 - 当同时打开多个弹窗时,遮罩只渲染一次,颜色取“最上层弹窗”的 `maskBg`。 ```ts DialogCustomStaticMethods.open(Comp, { maskBg: 'rgba(0,0,0,0.6)' }) ``` ## 多弹窗 ```tsx // 打开多个弹窗 DialogCustomStaticMethods.openWithFamily("settings", SettingsComponent) DialogCustomStaticMethods.openWithFamily("profile", ProfileComponent) // 或者通过 options.familyName 指定 DialogCustomStaticMethods.open(SettingsComponent, { familyName: 'settings' }) DialogCustomStaticMethods.open(ProfileComponent, { familyName: 'profile' }) // 关闭指定弹窗 DialogCustomStaticMethods.close("settings") // 关闭所有弹窗 DialogCustomStaticMethods.closeAll() ``` ## 回调方式 ### 方式1: onClose回调 ```tsx const result = await DialogCustomStaticMethods.open( ({ onClose }) => ( <div> <button onClick={() => onClose("保存")}>保存</button> <button onClick={() => onClose(null)}>取消</button> </div> ) ) // result = "保存" 或 null ``` ### 方式2: props回调 ```tsx const handleSave = (data) => console.log("保存:", data) await DialogCustomStaticMethods.open( ({ onSave, onClose }) => ( <div> <button onClick={() => onSave("数据")}>保存</button> <button onClick={() => onClose()}>关闭</button> </div> ), { props: { onSave: handleSave } } ) ``` ## 状态读取与订阅 > 这些 Hook/方法用于“读取弹窗状态”。推荐优先使用只读选择器,避免直接接触底层 Map。 ### useHasOpenDialog 是否存在任意弹窗打开(订阅式)。 ```tsx import { useHasOpenDialog } from '@/am-ui/am-dialog' export function Header() { const hasOpen = useHasOpenDialog() return hasOpen ? null : <TopBar /> } ``` ### useFamilyVisible 指定 family 是否打开(订阅式)。 ```tsx import { useFamilyVisible } from '@/am-ui/am-dialog' const profileOpen = useFamilyVisible('profile') ``` ### useDialogSelector 通用选择器 Hook:订阅式返回派生值,避免暴露底层 Map。 ```tsx import { useDialogSelector } from '@/am-ui/am-dialog' // 打开中的 family 列表 const openFamilies = useDialogSelector((states) => Array.from(states.entries()) .filter(([, s]) => s.visible) .map(([family]) => family), ) // 顶层弹窗标题(示例) const topTitle = useDialogSelector((states) => { const visible = Array.from(states.values()).filter((s) => s.visible && s.options) const top = visible[visible.length - 1] return top?.options?.title ?? '' }) ``` ### getDialogFrozenSnapshot 一次性只读快照(非订阅)。适合在非 React 或初始化时读取。 ```ts import { getDialogFrozenSnapshot } from '@/am-ui/am-dialog' const snap = getDialogFrozenSnapshot() for (const [family, state] of snap) { console.log(family, state.visible, state.options?.title) } ``` ### subscribeHasOpen 非 React 环境订阅“是否有弹窗打开”的变化(会立即回调一次当前值)。 ```ts import { subscribeHasOpen } from '@/am-ui/am-dialog' const unsubscribe = subscribeHasOpen((hasOpen) => { console.log('hasOpen changed:', hasOpen) }) // 需要时机合适地取消订阅 unsubscribe() ``` > 写操作请始终使用现有 API:`DialogCustomStaticMethods.open/openWithFamily/close/closeAll` 或内容组件内的 `onClose`/`onNext`,不要直接修改底层 Map。 ``` ## 🔗 相关链接 - [完整文档](https://github.com/ahmiao666/ahmiao-react-dialog-element) - [GitHub仓库](https://github.com/ahmiao666/ahmiao-react-dialog-element)