diff --git a/components/overlay/gateway.tsx b/components/overlay/gateway.tsx index e7f2d1927c..d0e17fd9af 100644 --- a/components/overlay/gateway.tsx +++ b/components/overlay/gateway.tsx @@ -21,7 +21,9 @@ class Gateway extends Component { }; static defaultProps = { - container: () => document.body, + container: () => { + if (typeof document !== 'undefined') return document.body; + }, }; child: Element | null | undefined; diff --git a/components/overlay/overlay.tsx b/components/overlay/overlay.tsx index 9bcf3a8a7b..bb34325c58 100644 --- a/components/overlay/overlay.tsx +++ b/components/overlay/overlay.tsx @@ -311,8 +311,8 @@ class Overlay extends Component { switch ((align as Array)[0]) { case 't': return { - // 为了防止有的用户 js升级了而css没升级,所以把两个动画都保留了。 - // 动画不会叠加,会替代,顺序根据 src/animate/main.scss 中的样式先后顺序遵循css覆盖原则 + // 为了防止有的用户 js 升级了而 css 没升级,所以把两个动画都保留了。 + // 动画不会叠加,会替代,顺序根据 src/animate/main.scss 中的样式先后顺序遵循 css 覆盖原则 // fadeInDownSmall fadeOutUpSmall 优先级更高 in: 'expandInDown fadeInDownSmall', out: 'expandOutUp fadeOutUpSmall', @@ -331,6 +331,9 @@ class Overlay extends Component { } addAnimationEvents() { + if (typeof window === 'undefined') { + return; + } setTimeout(() => { const node = this.getContentNode(); if (node) { @@ -399,8 +402,8 @@ class Overlay extends Component { }); this.onLeaved(); - // dom结构首次出现 触发的是entering - // dom结构已经存在(例如设置了cache),触发的是mounting + // dom 结构首次出现 触发的是 entering + // dom 结构已经存在(例如设置了 cache),触发的是 mounting } else if (this.state.status === 'entering' || this.state.status === 'mounting') { this.setState({ status: 'none', @@ -562,10 +565,11 @@ class Overlay extends Component { * document global event */ addDocumentEvents() { - // FIXME: canCloseByEsc、canCloseByOutSideClick、canCloseByMask仅在didMount时生效,update时不生效 + // FIXME: canCloseByEsc、canCloseByOutSideClick、canCloseByMask 仅在 didMount 时生效,update 时不生效 const { useCapture } = this.props; // use capture phase listener to be compatible with react17 // https://reactjs.org/blog/2020/08/10/react-v17-rc.html#fixing-potential-issues + if (typeof document === undefined) return; if (this.props.canCloseByEsc) { this._keydownEvents = events.on( document, @@ -622,7 +626,7 @@ class Overlay extends Component { const path = [] as Array; while (el) { path.push(el); - if (el.tagName === 'HTML') { + if (el.tagName === 'HTML' && typeof document !== undefined) { path.push(document); path.push(window); return path; @@ -658,9 +662,14 @@ class Overlay extends Component { node && (node === e.target || node.contains(e.target as HTMLElement) || - this.matchInShadowDOM(node, e) || - (e.target !== document && - !document.documentElement.contains(e.target as HTMLElement))) + this.matchInShadowDOM(node, e)) + ) { + return; + } + if (typeof document === undefined) return; + if ( + e.target !== document && + !document.documentElement.contains(e.target as HTMLElement) ) { return; } @@ -690,7 +699,7 @@ class Overlay extends Component { this.gatewayRef = ref; }; - // 兼容过去的用法: this.popupRef.getInstance().overlay.getInstance().getContentNode() + // 兼容过去的用法:this.popupRef.getInstance().overlay.getInstance().getContentNode() getInstance() { return this; } diff --git a/components/overlay/popup.tsx b/components/overlay/popup.tsx index 73be6dcb4a..352c5e5761 100644 --- a/components/overlay/popup.tsx +++ b/components/overlay/popup.tsx @@ -59,11 +59,11 @@ class Popup extends Component { */ delay: PropTypes.number, /** - * 鼠标放置后的延时显示, 单位毫秒 ms + * 鼠标放置后的延时显示,单位毫秒 ms */ mouseEnterDelay: PropTypes.number, /** - * 鼠标离开后的延时显示, 单位毫秒 ms + * 鼠标离开后的延时显示,单位毫秒 ms */ mouseLeaveDelay: PropTypes.number, /** @@ -76,7 +76,7 @@ class Popup extends Component { target: PropTypes.any, safeNode: PropTypes.any, /** - * 是否跟随trigger滚动 + * 是否跟随 trigger 滚动 */ followTrigger: PropTypes.bool, container: PropTypes.any, @@ -111,7 +111,9 @@ class Popup extends Component { delay: 200, canCloseByTrigger: true, followTrigger: false, - container: () => document.body, + container: () => { + if (typeof document !== 'undefined') return document.body; + }, rtl: false, }; _mouseNotFirstOnMask: boolean; diff --git a/components/overlay/position.tsx b/components/overlay/position.tsx index 1d8642e76a..0b256c2aa2 100644 --- a/components/overlay/position.tsx +++ b/components/overlay/position.tsx @@ -62,7 +62,9 @@ export default class Position extends Component { this.setPosition(); if (this.props.needListenResize) { - events.on(window, 'resize', this.handleResize); + if (typeof window !== 'undefined') { + events.on(window, 'resize', this.handleResize); + } this.observe(); } } @@ -84,7 +86,9 @@ export default class Position extends Component { componentWillUnmount() { if (this.props.needListenResize) { - events.off(window, 'resize', this.handleResize); + if (typeof window !== 'undefined') { + events.off(window, 'resize', this.handleResize); + } this.unobserve(); } diff --git a/components/overlay/utils/find-node.ts b/components/overlay/utils/find-node.ts index 9b27c2c6b4..8d22fbb5f3 100644 --- a/components/overlay/utils/find-node.ts +++ b/components/overlay/utils/find-node.ts @@ -7,7 +7,7 @@ export default function findNode(target?: Target, param?: T): Element | Te return null; } - if (typeof realTarget === 'string') { + if (typeof realTarget === 'string' && typeof document !== 'undefined') { return document.getElementById(realTarget); } @@ -24,7 +24,7 @@ export default function findNode(target?: Target, param?: T): Element | Te } try { - // @ts-expect-error realTarget需要判断是否是ReactInstance,还会存在Element Node Text的情况 + // @ts-expect-error realTarget 需要判断是否是 ReactInstance,还会存在 Element Node Text 的情况 return findDOMNode(realTarget); } catch (err) { // @ts-expect-error 这个兜底逻辑十分破坏类型完备 diff --git a/components/overlay/utils/position.ts b/components/overlay/utils/position.ts index 90fd78ce0b..36e3a7ba06 100644 --- a/components/overlay/utils/position.ts +++ b/components/overlay/utils/position.ts @@ -6,8 +6,12 @@ import type { PositionProps, PointsType } from '../types'; const VIEWPORT = 'viewport' as const; // IE8 not support pageXOffset -const getPageX = () => window.pageXOffset || document.documentElement.scrollLeft; -const getPageY = () => window.pageYOffset || document.documentElement.scrollTop; +const getPageX = () => { + return window.pageXOffset || document.documentElement.scrollLeft; +}; +const getPageY = () => { + return window.pageYOffset || document.documentElement.scrollTop; +}; /** * @internal get element size @@ -98,7 +102,7 @@ function _getViewportSize(container: HTMLElement | SVGElement) { } const getContainer = ({ container, baseElement }: PositionProps) => { - // SSR下会有副作用 + // SSR 下会有副作用 if (typeof document === 'undefined') { return container; } @@ -257,11 +261,11 @@ export default class Position { if (this.autoFit && align && this.container && this.container !== document.body) { const baseElementRect = _getElementRect( - // @ts-expect-error _getElementRect baseElement不支持"viewport" 需要对baseElement做非"viewport"处理 + // @ts-expect-error _getElementRect baseElement 不支持"viewport" 需要对 baseElement 做非"viewport"处理 this.baseElement, this.container ); - // @ts-expect-error _getElementRect pinElement不支持"viewport" 需要对pinElement做非"viewport"处理 + // @ts-expect-error _getElementRect pinElement 不支持"viewport" 需要对 pinElement 做非"viewport"处理 const pinElementRect = _getElementRect(this.pinElement, this.container); const viewportSize = _getViewportSize(this.container); const pinAlign = align.split(' ')[0]; @@ -399,7 +403,7 @@ export default class Position { docElement = document.documentElement; result.offset = (ignoreScroll: boolean) => { - // 这里是关键,第二个参数的含义以ing该是:是否为 fixed 布局,并且像 dialog 一样,不跟随 trigger 元素 + // 这里是关键,第二个参数的含义以 ing 该是:是否为 fixed 布局,并且像 dialog 一样,不跟随 trigger 元素 if (ignoreElementOffset) { return { left: 0, @@ -446,9 +450,9 @@ export default class Position { // According to the location of the overflow to calculate the desired positioning _getExpectedAlign() { - // @ts-expect-error align这里需要确定是string,不能是boolean + // @ts-expect-error align 这里需要确定是 string,不能是 boolean const align: string = this.isRtl - ? // @ts-expect-error align这里需要确定是string,不能是boolean + ? // @ts-expect-error align 这里需要确定是 string,不能是 boolean this._replaceAlignDir(this.align, /l|r/g, { l: 'r', r: 'l' }) : this.align; const expectedAlign = [align];