
UI组件前端【免费下载链接】react-modalAccessible modal dialog component for React项目地址https://gitcode.com/gh_mirrors/re/react-modal点击查看免费下载react-modal 是一个以无障碍Accessibility为第一优先级的 React 弹窗Modal Dialog组件遵循 WAI-ARIA 规范在提供功能完备、可直接用于生产环境的弹窗能力的同时保证屏幕阅读器等辅助技术用户可以获得与其他用户一致的体验。本文以仓库 docs/index.md 的 API 说明为骨架结合 Modal.js 与 ModalPortal.js 的源码实现系统讲解安装方式、全部 Props 的语义与默认值、自定义父节点、Ref 回调以及 ARIA 与焦点管理背后的真实执行逻辑读完即可在项目中正确地接入并配置 react-modal。安装方式react-modal 支持通过 npm 或 yarn 安装稳定版本$ npm install react-modal $ yarn add react-modal在 React 的 CDN 应用中需要在 React 的 CDN 脚本之后、你自己的 JS 文件之前引入 CDN 脚本然后在应用中使用ReactModal标签script srchttps://cdnjs.cloudflare.com/ajax/libs/react-modal/3.14.3/react-modal.min.js integritysha512-MY2jfK3DBnVzdS2V8MXo5lRtr0mNRroUI9hoLVv2/yL3vrJTam3VzASuKQ96fLEpyYIT4a8o7YgtUs5lPjiLVQ crossoriginanonymous referrerpolicyno-referrer/script从仓库 package.json 的 peerDependencies 可以看出react-modal 支持 React 0.14 至 19 的广泛版本范围react: ^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18 || ^19。在 React 16 及以上版本中组件通过ReactDOM.createPortal挂载弹窗内容见 Modal.js 中的getCreatePortal逻辑在更早版本中则回退到ReactDOM.unstable_renderSubtreeIntoContainer。通用用法与全部 Props 详解react-modal 唯一必填的 prop 是isOpen它决定弹窗是否显示。下面是一个指定了全部可用 props 与选项的完整示例来自 docs/index.md 的 General Usage 部分import ReactModal from react-modal; ReactModal isOpen{false /* Boolean 描述弹窗是否应该显示 */} onAfterOpen{handleAfterOpenFunc /* 弹窗打开后执行的回调函数 */} onAfterClose{handleAfterCloseFunc /* 弹窗关闭后执行的回调函数 */} onRequestClose{handleRequestCloseFunc /* 弹窗被请求关闭时执行的回调点击 overlay 或按 ESC 触发。 注意通过其他方式改变 isOpen 不会调用它。 */} closeTimeoutMS{0 /* 关闭弹窗前等待的毫秒数 */} style{{ overlay: {}, content: {} } /* 弹窗样式对象包含 overlay 与 content 两个键。 详见 Styles 相关章节。 */} contentLabelExample Modal /* 字符串屏幕阅读器对内容容器的可访问名称 */} portalClassNameReactModalPortal /* 应用于 portal 的 className */} overlayClassNameReactModal__Overlay /* 应用于 overlay 的 className */} idsome-id /* 应用于内容 div 的 id */} classNameReactModal__Content /* 应用于弹窗内容的 className */} bodyOpenClassNameReactModal__Body--open /* 应用于弹窗 ownerDocument.body 的 className 必须是常量字符串。设为 null 时不会给 document.body 添加任何类。 */} htmlOpenClassNameReactModal__Html--open /* 应用于弹窗 ownerDocument.html 的 className 必须是常量字符串。默认值为 null。 */} ariaHideApp{true /* Boolean指示是否隐藏 appElement */} shouldFocusAfterRender{true /* Boolean指示渲染后弹窗是否应获得焦点 */} shouldCloseOnOverlayClick{true /* Boolean指示点击 overlay 是否关闭弹窗 */} shouldCloseOnEsc{true /* Boolean指示按 ESC 键是否关闭弹窗。 注意禁用 ESC 关闭弹窗可能引入无障碍问题。 */} shouldReturnFocusAfterClose{true /* Boolean指示弹窗关闭后是否将焦点恢复到 显示之前获得焦点的元素。 */} roledialog /* 字符串指示弹窗的角色默认值为 dialog。 */} preventScroll{false /* Boolean指示恢复焦点时是否使用 preventScroll 标志。 */} parentSelector{() document.body /* 函数被调用以获取弹窗要挂载到的父元素。 */} aria{{ labelledby: heading, describedby: full_description } /* 附加 ARIA 属性可选。 */} data{{ background: green } /* 附加 data 属性可选。 */} testId /* 字符串渲染>Modal // ... parentSelector{() document.querySelector(#root)} pModal Content./p /Modal需要特别注意如果这样做请务必正确设置 app element。app element不应是弹窗的父元素否则弹窗打开时其内容会被屏幕阅读器隐藏。从源码看当parentSelector返回值在运行时发生变化时组件会通过getSnapshotBeforeUpdate捕获新旧父节点Modal.js并在componentDidUpdate中把 portal 容器从旧父节点移动到新父节点Modal.js。卸载时若父节点已不存在会输出警告提示避免内存泄漏Modal.js。Refs获取 Overlay 与 Content 的 DOM 节点你可以使用 ref 回调直接获取 overlay 和 content 的 DOM 节点Modal // ... overlayRef{node (this.overlayRef node)} contentRef{node (this.contentRef node)} pModal Content./p /Modal在 ModalPortal.js 中setOverlayRef与setContentRef会先将节点保存到实例属性this.overlay/this.content再转发给用户传入的overlayRef/contentRef回调。这两个内部引用还被用于onAfterOpen回调参数中的overlayEl/contentEl见 ModalPortal.js、点击 overlay 时的焦点重定向focusContent以及 Tab 键焦点圈定scopeTab(this.content, event)。样式系统内联样式与 CSS 类默认内联样式与合并规则通过styleprop 传入的样式会与默认样式合并。默认样式定义在Modal.defaultStyles对象中Modal.jsModal ... style{{ overlay: { position: fixed, top: 0, left: 0, right: 0, bottom: 0, backgroundColor: rgba(255, 255, 255, 0.75) }, content: { position: absolute, top: 40px, left: 40px, right: 40px, bottom: 40px, border: 1px solid #ccc, background: #fff, overflow: auto, WebkitOverflowScrolling: touch, borderRadius: 4px, outline: none, padding: 20px } }} ... 在 ModalPortal.js 的渲染逻辑中contentStyles与overlayStyles的选取遵循如下规则指定了className则禁用 content 的默认样式指定了overlayClassName则禁用 overlay 的默认样式之后通过{ ...defaultStyles.xxx, ...this.props.style.xxx }的展开合并方式将自定义内联样式覆盖到默认样式之上见 ModalPortal.js。你也可以直接修改Modal.defaultStyles来更改全局默认样式。默认样式的完整定义可见 docs/styles/index.md 与 Modal.js。使用 CSS 类控制样式关于className/overlayClassName的详细用法请参阅 docs/styles/classes.md其核心规则如下每个 prop 可以是单个字符串应用于对应组件也可以是一个包含base、afterOpen、beforeClose三个键的对象。base始终应用于组件afterOpen弹窗打开后应用beforeClose弹窗被请求关闭后应用如用户按 ESC 或点击 overlay。beforeClose类只有在closeTimeoutMS设置为非零值时才有效果否则弹窗被请求关闭时会立即关闭。因此若要利用afterOpen/beforeClose实现过渡动画应把closeTimeoutMS设为关闭过渡动画的时长毫秒。指定className后默认 content 样式 不再应用指定overlayClassName后默认 overlay 样式不再应用。若未指定类名overlay 会应用默认类ReactModal__Overlay、ReactModal__Overlay--after-open、ReactModal__Overlay--before-closecontent 使用对应的ReactModal__Content前缀。这些默认类上附加的样式不会覆盖默认内联样式与通过className/overlayClassName指定类时的行为不同。这一行为在源码中体现为buildClassName方法ModalPortal.js当传入对象时使用对象的base/afterOpen/beforeClose否则使用默认类名常量CLASS_NAMES定义于 ModalPortal.js并根据afterOpen/beforeClose状态追加对应的后缀类。document.body 与 html 标签的类通过bodyOpenClassName可以覆盖弹窗打开时添加到document.body的默认类默认值为ReactModal__Body--open。它必须是常量字符串因为同时打开多个弹窗时系统需要管理从哪个弹窗的哪个类名设为null时不添加任何类也支持用空格分隔同时添加多个类。一个典型用途是打开弹窗时禁止 body 滚动.ReactModal__Body--open { overflow: hidden; }htmlOpenClassName用于给html标签添加类默认值为null规则与bodyOpenClassName相同必须是常量字符串可帮助避免打开弹窗时页面滚动到顶部.ReactModal__Body--open, .ReactModal__Html--open { overflow: hidden; }通过portalClassName可以给整个 portal 指定类名默认不对 portal 本身应用任何样式。在源码中beforeOpen会向parentDocument.body与parentDocument的 html 元素添加bodyOpenClassName/htmlOpenClassNameModalPortal.jsafterClose时对称移除ModalPortal.js。开发模式下若这两个类名在运行中被修改会输出警告提示可能造成多弹窗场景的意外行为ModalPortal.js。无障碍Accessibility特性react-modal 以 WAI-ARIA 指南为基准实现无障碍支持完整说明见 docs/accessibility/index.md。App Element屏幕阅读器隔离对屏幕阅读器用户而言弹窗打开时页面其他内容应通过aria-hidden属性被隐藏。为此应调用Modal.setAppElement并传入标识应用根节点的选择器例如应用内容位于 ID 为root的元素内时Modal.setAppElement(#root);也可以直接传入 DOM 元素Modal.setAppElement(document.getElementById(root));使用匹配多个元素的选择器或传入 DOM 元素列表时所有元素都会被隐藏。注意如果元素从 DOM 中移除这个列表不会自动修剪因此元素结构变化时可能需要重新调用Modal.setAppElement或者直接传入实时的 HTMLCollection。如果你已经通过其他方式给应用内容施加了aria-hidden可以传入ariaHideApp{false}来避免未指定 app element的警告。Modal.setAppElement不会把 react-modal 嵌入为你的 React 应用的子组件它只负责提升应用的无障碍性。从源码看setAppElement内部调用ariaAppHider.setElementModal.js。ariaAppHider.js 会解析字符串选择器使用document.querySelectorAll无匹配时抛出错误随后hide/show对每个匹配元素施加或移除aria-hidden属性ariaAppHider.js。若未设置 app elementvalidateElement会输出警告提示使用Modal.setAppElement(el)或设置appElement{el}并说明可通过ariaHideApp{false}选择退出ariaAppHider.js。弹窗打开/关闭时aria-hidden的管理由 ModalPortal.js 完成每次打开弹窗ariaHiddenInstances计数器加一只有计数器归零即所有弹窗都已关闭时才移除aria-hidden这保证了多弹窗嵌套场景下的正确性。键盘导航焦点圈定与还原弹窗打开时Tab 键导航会被限制在弹窗内容内的元素之间避免弹窗外打开时不可见的元素意外获得焦点。实现上handleKeyDown在检测到 Tab 键时调用scopeTab(this.content, event)ModalPortal.js具体的焦点圈定逻辑见 scopeTab.js。默认情况下弹窗关闭时焦点会恢复到打开前获得焦点的元素传入shouldReturnFocusAfterClose{false}可禁用此行为。焦点还原由 focusManager.js 的returnFocus实现打开时markForFocusLater将当前活动元素压入栈focusManager.js关闭时弹出并调用toFocus.focus({ preventScroll })preventScroll参数由preventScrollprop 控制。弹窗默认可通过 ESC 键关闭除非传入shouldCloseOnEsc{false}。禁用该行为可能给键盘用户带来无障碍问题因此不推荐禁用。此外弹窗内容容器默认带有tabIndex-1ModalPortal.js且focusContent方法会在不偷取内部元素焦点的情况下将焦点聚焦到内容容器ModalPortal.js。ARIA 属性除了应用到 app element 上的aria-hiddenreact-modal 还支持许多其他 ARIA 属性完整列表见 WAI-ARIA 1.1 规范contentLabelprop当界面上没有可见标签时用它为弹窗内容提供aria-label。若弹窗已有可见文本标签应通过ariaprop 以aria-labelledby指定包含标签的元素。ariaprop 接受一个对象键为要设置的属性名不带aria-前缀。例如一个带标题和较长描述的 alert 弹窗Modal isOpen{modalIsOpen} aria{{ labelledby: heading, describedby: full_description }} h1 idheadingAlert/h1 div idfull_description pDescription goes here./p /div /Modal源码层面ModalPortal.js 的attributesFromObject会把对象键加上aria-/data-前缀后展开到内容容器上aria对象默认合并了modal: true即aria-modaltruedata对象展开为data-*属性testId则渲染为data-testid见 ModalPortal.js。关闭过渡动画与 closeTimeoutMS 的配合借助 CSS 类可以实现弹窗打开与关闭时的过渡动画。将以下 CSS 放入项目样式后弹窗内容即可实现打开淡入、关闭淡出.ReactModal__Overlay { opacity: 0; transition: opacity 2000ms ease-in-out; } .ReactModal__Overlay--after-open{ opacity: 1; } .ReactModal__Overlay--before-close{ opacity: 0; }上述示例会全局作用于所有未通过classNameprop 自定义afterOpen/beforeClose类的弹窗若要只作用于单个弹窗可修改类名并将对象形式传给classNameprop详见 docs/styles/transitions.md。为了让过渡动画生效必须把动画时长告知Modal /即Modal closeTimeoutMS{2000} /closeTimeoutMS以毫秒为单位其值与 CSS或styleprop中使用的动画时长需要保持一致。若使用React 16关闭过渡只能通过用isOpenprop 切换弹窗可见性来实现不要对Modal /做条件渲染。不要这样写{ this.state.showModal Modal closeTimeoutMS{200} isOpen contentLabelmodal onRequestClose{() this.toggleModal()} h2Add modal content here/h2 /Modal }而应这样写{ Modal closeTimeoutMS{200} isOpen{this.state.showModal} contentLabelmodal onRequestClose{() this.toggleModal()} h2Add modal content here/h2 /Modal }原因在于React Modal 采用了 React 16 的稳定 Portal APIcreatePortal而该 API 不允许开发者干预 portal 组件的卸载过程条件渲染会导致弹窗被立即卸载beforeClose过渡动画无法执行。源码实现中关闭时closeWithTimeout会先设置beforeClose: true并记录closesAt时间戳再通过setTimeout在closeTimeoutMS毫秒后真正完成关闭ModalPortal.jsbuildClassName会在该状态下为 overlay / content 追加--before-close类以触发退出动画而在closeWithoutTimeoutcloseTimeoutMS为 0时则立即关闭、跳过过渡。事件回调与关闭语义onRequestClose是弹窗被请求关闭时的回调触发来源包括点击 overlay 与按 ESC 键但不会在通过其他方式改变isOpen时被调用。源码中ESC 键handleKeyDown在shouldCloseOnEsc为 true 且检测到 Escape 键时调用requestClose(event)ModalPortal.js点击 overlayhandleOverlayOnClick在shouldCloseOnOverlayClick为 true 时调用requestCloseModalPortal.js并配合 mousedown/mouseup/click 事件链判断点击是否发生在 content 内部避免误判requestClose最终只在存在onRequestClose回调时才触发ModalPortal.js。onAfterOpen在弹窗打开后于下一帧触发回调参数中包含{ overlayEl, contentEl }ModalPortal.js方便在打开动画完成后操作 DOMonAfterClose在关闭流程全部完成、类名移除与焦点还原之后触发ModalPortal.js。本地示例与开发examples目录包含多种可直接本地运行的基础示例运行方式为$ npm start或$ yarn start然后浏览器访问localhost:8080详见 docs/examples/index.md。仓库中已有的示例包括 simple_usage、nested_modals、multiple_modals、react-router 等可分别查看弹窗的基本用法、嵌套弹窗与多弹窗场景。相关测试位于 specs 目录如 Modal.events.spec.js、Modal.style.spec.js通过npm testKarma即可运行验证各行为的正确性。小结react-modal 的核心价值在于把无障碍做好从Modal.setAppElement对背景内容的aria-hidden隔离到 Tab 键焦点圈定与关闭后焦点还原再到aria-modal、aria-label/aria-labelledby的自动装配每一项都对应 ModalPortal.js 与 src/helpers 中可验证的源码实现。配合本文梳理的默认值与全部 Props 语义你可以精准控制挂载位置、样式与过渡动画、关闭行为与无障碍细节在各类 React 应用中构建合规、可用、可测试的弹窗体验。赞分享UI组件前端【免费下载链接】react-modalAccessible modal dialog component for React项目地址https://gitcode.com/gh_mirrors/re/react-modal点击查看免费下载相关推荐React-Modal无障碍开发工具axe DevTools使用指南React Modal无障碍开发工具axe DevTools使用指南 你是否曾因模态框Modal的无障碍问题收到用户投诉是否在上线前反复检查却仍遗漏键盘UI组件前端shadcn-vue Label 组件完全指南从安装、源码解析到无障碍表单实践shadcn vue Label 组件完全指南从安装、源码解析到无障碍表单实践 导读 Label 是 shadcn vue 中用于为表单控件输入框、复选框、UI组件前端Base UI React Autocomplete 组件 API 全解析从 Root Props 到定位、过滤与无障碍实现Base UI React Autocomplete 组件 API 全解析从 Root Props 到定位、过滤与无障碍实现 本文以 Base UIbase前端UI组件上一篇QuantsPlaybook深度解析如何用Python完美复现A股量化策略下一篇如何打造属于你的数字记忆宝库WeChatMsg让聊天记录真正属于你创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考