From 6851c71e46a1a8be9f734df9737d047e8620e880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=88=E8=90=BD=E9=9F=B3=E9=98=91?= <424532913@qq.com> Date: Fri, 31 Dec 2021 14:58:39 +0800 Subject: [PATCH] feat: add ssr support (#186) --- .../core/src/drivers/ViewportResizeDriver.ts | 6 +- .../core/src/drivers/ViewportScrollDriver.ts | 4 +- .../src/effects/useContentEditableEffect.ts | 8 +-- .../src/events/cursor/AbstractCursorEvent.ts | 5 +- .../events/viewport/AbstractViewportEvent.ts | 17 ++--- packages/core/src/index.ts | 9 +-- packages/core/src/internals.ts | 7 +- packages/core/src/models/Cursor.ts | 3 +- packages/core/src/models/Engine.ts | 4 +- packages/core/src/models/Viewport.ts | 69 ++++++++++++------- packages/react-sandbox/src/index.ts | 12 ++-- .../src/shared/loadScript.ts | 11 +-- packages/react/src/containers/Viewport.tsx | 4 +- packages/react/src/hooks/useDesigner.ts | 5 +- packages/react/src/hooks/useLayout.ts | 6 +- packages/react/src/hooks/useRegistry.ts | 3 +- packages/react/src/hooks/useWorkspace.ts | 6 +- .../react/src/widgets/OutlineWidget/index.tsx | 3 +- packages/shared/src/coordinate.ts | 61 ++++++++++------ packages/shared/src/event.ts | 5 +- packages/shared/src/globalThisPolyfill.ts | 19 +++++ packages/shared/src/index.ts | 1 + packages/shared/src/instanceof.ts | 6 +- packages/shared/src/request-idle.ts | 5 +- 24 files changed, 180 insertions(+), 99 deletions(-) create mode 100644 packages/shared/src/globalThisPolyfill.ts diff --git a/packages/core/src/drivers/ViewportResizeDriver.ts b/packages/core/src/drivers/ViewportResizeDriver.ts index 57873eab3..94c2b32a1 100644 --- a/packages/core/src/drivers/ViewportResizeDriver.ts +++ b/packages/core/src/drivers/ViewportResizeDriver.ts @@ -2,6 +2,8 @@ import { EventDriver } from '@designable/shared' import { Engine } from '../models/Engine' import { ViewportResizeEvent } from '../events' import { ResizeObserver } from '@juggle/resize-observer' +import { globalThisPolyfill } from '@designable/shared' + export class ViewportResizeDriver extends EventDriver { request = null @@ -27,7 +29,7 @@ export class ViewportResizeDriver extends EventDriver { } attach() { - if (this.contentWindow && this.contentWindow !== window) { + if (this.contentWindow && this.contentWindow !== globalThisPolyfill) { this.addEventListener('resize', this.onResize) } else { if (this.container && this.container !== document) { @@ -38,7 +40,7 @@ export class ViewportResizeDriver extends EventDriver { } detach() { - if (this.contentWindow && this.contentWindow !== window) { + if (this.contentWindow && this.contentWindow !== globalThisPolyfill) { this.removeEventListener('resize', this.onResize) } else if (this.resizeObserver) { if (this.container && this.container !== document) { diff --git a/packages/core/src/drivers/ViewportScrollDriver.ts b/packages/core/src/drivers/ViewportScrollDriver.ts index 1c2e7496b..c3a694a78 100644 --- a/packages/core/src/drivers/ViewportScrollDriver.ts +++ b/packages/core/src/drivers/ViewportScrollDriver.ts @@ -1,4 +1,4 @@ -import { EventDriver } from '@designable/shared' +import { EventDriver, globalThisPolyfill } from '@designable/shared' import { Engine } from '../models/Engine' import { ViewportScrollEvent } from '../events' @@ -7,7 +7,7 @@ export class ViewportScrollDriver extends EventDriver { onScroll = (e: UIEvent) => { e.preventDefault() - this.request = window.requestAnimationFrame(() => { + this.request = globalThisPolyfill.requestAnimationFrame(() => { this.dispatch( new ViewportScrollEvent({ scrollX: this.contentWindow.scrollX, diff --git a/packages/core/src/effects/useContentEditableEffect.ts b/packages/core/src/effects/useContentEditableEffect.ts index f12555b58..5d0b54bea 100644 --- a/packages/core/src/effects/useContentEditableEffect.ts +++ b/packages/core/src/effects/useContentEditableEffect.ts @@ -1,5 +1,5 @@ import { Path } from '@formily/path' -import { requestIdle } from '@designable/shared' +import { requestIdle, globalThisPolyfill } from '@designable/shared' import { Engine, TreeNode } from '../models' import { MouseDoubleClickEvent, MouseClickEvent } from '../events' @@ -27,17 +27,17 @@ function setEndOfContenteditable(contentEditableElement: Element) { const range = document.createRange() range.selectNodeContents(contentEditableElement) range.collapse(false) - const selection = window.getSelection() + const selection = globalThisPolyfill.getSelection() selection.removeAllRanges() selection.addRange(range) } function createCaretCache(el: Element) { - const currentSelection = window.getSelection() + const currentSelection = globalThisPolyfill.getSelection() if (currentSelection.containsNode(el)) return const ranges = getAllRanges(currentSelection) return () => { - const sel = window.getSelection() + const sel = globalThisPolyfill.getSelection() const firstNode = el.childNodes[0] if (!firstNode) return sel.removeAllRanges() diff --git a/packages/core/src/events/cursor/AbstractCursorEvent.ts b/packages/core/src/events/cursor/AbstractCursorEvent.ts index 78eb872a7..bda295d06 100644 --- a/packages/core/src/events/cursor/AbstractCursorEvent.ts +++ b/packages/core/src/events/cursor/AbstractCursorEvent.ts @@ -1,4 +1,5 @@ import { IEngineContext } from '../../types' +import { globalThisPolyfill } from '@designable/shared' export interface ICursorEventOriginData { clientX: number @@ -28,14 +29,14 @@ export class AbstractCursorEvent { pageX: 0, pageY: 0, target: null, - view: window, + view: globalThisPolyfill, } this.transformCoordinates() } transformCoordinates() { const { frameElement } = this.data?.view || {} - if (frameElement && this.data.view !== window) { + if (frameElement && this.data.view !== globalThisPolyfill) { const frameRect = frameElement.getBoundingClientRect() const scale = frameRect.width / frameElement['offsetWidth'] this.data.topClientX = this.data.clientX * scale + frameRect.x diff --git a/packages/core/src/events/viewport/AbstractViewportEvent.ts b/packages/core/src/events/viewport/AbstractViewportEvent.ts index 5fd7744dc..445fc50eb 100644 --- a/packages/core/src/events/viewport/AbstractViewportEvent.ts +++ b/packages/core/src/events/viewport/AbstractViewportEvent.ts @@ -1,4 +1,5 @@ import { IEngineContext } from '../../types' +import { globalThisPolyfill } from '@designable/shared' export interface IViewportEventData { scrollX: number @@ -16,14 +17,14 @@ export class AbstractViewportEvent { context: IEngineContext constructor(data: IViewportEventData) { this.data = data || { - scrollX: window.scrollX, - scrollY: window.scrollY, - width: window.innerWidth, - height: window.innerHeight, - innerWidth: window.innerWidth, - innerHeight: window.innerHeight, - view: window, - target: window, + scrollX: globalThisPolyfill.scrollX, + scrollY: globalThisPolyfill.scrollY, + width: globalThisPolyfill.innerWidth, + height: globalThisPolyfill.innerHeight, + innerWidth: globalThisPolyfill.innerWidth, + innerHeight: globalThisPolyfill.innerHeight, + view: globalThisPolyfill, + target: globalThisPolyfill, } } } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 809a60f3a..9a77d670a 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,14 +1,15 @@ import * as Core from './exports' export * from './exports' +import { globalThisPolyfill } from '@designable/shared' -if (window?.['Designable']?.['Core']) { +if (globalThisPolyfill?.['Designable']?.['Core']) { if (module.exports) { module.exports = { __esModule: true, - ...window['Designable']['Core'], + ...globalThisPolyfill['Designable']['Core'], } } } else { - window['Designable'] = window['Designable'] || {} - window['Designable'].Core = Core + globalThisPolyfill['Designable'] = globalThisPolyfill['Designable'] || {} + globalThisPolyfill['Designable'].Core = Core } diff --git a/packages/core/src/internals.ts b/packages/core/src/internals.ts index 9787b571c..dde3cd6df 100644 --- a/packages/core/src/internals.ts +++ b/packages/core/src/internals.ts @@ -1,4 +1,5 @@ import { each, isPlainObj } from '@designable/shared' +import { globalThisPolyfill } from '@designable/shared' export const lowerSnake = (str: string) => { return String(str).replace(/\s+/g, '_').toLocaleLowerCase() @@ -25,10 +26,12 @@ export const mergeLocales = (target: any, source: any) => { export const getBrowserLanguage = () => { /* istanbul ignore next */ - if (!window.navigator) { + if (!globalThisPolyfill.navigator) { return 'en' } return ( - window.navigator['browserlanguage'] || window.navigator?.language || 'en' + globalThisPolyfill.navigator['browserlanguage'] || + globalThisPolyfill.navigator?.language || + 'en' ) } diff --git a/packages/core/src/models/Cursor.ts b/packages/core/src/models/Cursor.ts index a8aabb612..9404445b7 100644 --- a/packages/core/src/models/Cursor.ts +++ b/packages/core/src/models/Cursor.ts @@ -1,5 +1,6 @@ import { Engine } from './Engine' import { action, define, observable } from '@formily/reactive' +import { globalThisPolyfill } from '@designable/shared' export enum CursorStatus { Normal = 'NORMAL', @@ -92,7 +93,7 @@ export class Cursor { dragEndScrollOffset: IScrollOffset = DEFAULT_SCROLL_OFFSET - view: Window = window + view: Window = globalThisPolyfill constructor(engine: Engine) { this.engine = engine diff --git a/packages/core/src/models/Engine.ts b/packages/core/src/models/Engine.ts index 0a67c1deb..095eed4cd 100644 --- a/packages/core/src/models/Engine.ts +++ b/packages/core/src/models/Engine.ts @@ -4,7 +4,7 @@ import { Workbench } from './Workbench' import { Cursor } from './Cursor' import { Keyboard } from './Keyboard' import { Screen, ScreenType } from './Screen' -import { Event, uid } from '@designable/shared' +import { Event, uid, globalThisPolyfill } from '@designable/shared' /** * 设计器引擎 @@ -80,7 +80,7 @@ export class Engine extends Event { } mount() { - this.attachEvents(window) + this.attachEvents(globalThisPolyfill) } unmount() { diff --git a/packages/core/src/models/Viewport.ts b/packages/core/src/models/Viewport.ts index da3cfcf2a..b589fe6c4 100644 --- a/packages/core/src/models/Viewport.ts +++ b/packages/core/src/models/Viewport.ts @@ -6,6 +6,7 @@ import { IPoint, requestIdle, cancelIdle, + globalThisPolyfill, } from '@designable/shared' import { action, define, observable } from '@formily/reactive' import { Workspace } from './Workspace' @@ -96,7 +97,7 @@ export class Viewport { } get isMaster() { - return this.contentWindow === window + return this.contentWindow === globalThisPolyfill } get isIframe() { @@ -114,7 +115,10 @@ export class Viewport { get innerRect() { const rect = this.rect - return new DOMRect(0, 0, rect?.width, rect?.height) + return ( + typeof DOMRect !== 'undefined' && + new DOMRect(0, 0, rect?.width, rect?.height) + ) } get offsetX() { @@ -277,11 +281,14 @@ export class Viewport { const offsetHeight = element['offsetHeight'] ? element['offsetHeight'] : rect.height - return new DOMRect( - rect.x, - rect.y, - this.scale !== 1 ? offsetWidth : rect.width, - this.scale !== 1 ? offsetHeight : rect.height + return ( + typeof DOMRect !== 'undefined' && + new DOMRect( + rect.x, + rect.y, + this.scale !== 1 ? offsetWidth : rect.width, + this.scale !== 1 ? offsetHeight : rect.height + ) ) } @@ -296,14 +303,20 @@ export class Viewport { ) if (rect) { if (this.isIframe) { - return new DOMRect( - rect.x + this.offsetX, - rect.y + this.offsetY, - rect.width, - rect.height + return ( + typeof DOMRect !== 'undefined' && + new DOMRect( + rect.x + this.offsetX, + rect.y + this.offsetY, + rect.width, + rect.height + ) ) } else { - return new DOMRect(rect.x, rect.y, rect.width, rect.height) + return ( + typeof DOMRect !== 'undefined' && + new DOMRect(rect.x, rect.y, rect.width, rect.height) + ) } } } @@ -320,20 +333,26 @@ export class Viewport { ) if (elementRect) { if (this.isIframe) { - return new DOMRect( - elementRect.x + this.contentWindow.scrollX, - elementRect.y + this.contentWindow.scrollY, - elementRect.width, - elementRect.height + return ( + typeof DOMRect !== 'undefined' && + new DOMRect( + elementRect.x + this.contentWindow.scrollX, + elementRect.y + this.contentWindow.scrollY, + elementRect.width, + elementRect.height + ) ) } else { - return new DOMRect( - (elementRect.x - this.offsetX + this.viewportElement.scrollLeft) / - this.scale, - (elementRect.y - this.offsetY + this.viewportElement.scrollTop) / - this.scale, - elementRect.width, - elementRect.height + return ( + typeof DOMRect !== 'undefined' && + new DOMRect( + (elementRect.x - this.offsetX + this.viewportElement.scrollLeft) / + this.scale, + (elementRect.y - this.offsetY + this.viewportElement.scrollTop) / + this.scale, + elementRect.width, + elementRect.height + ) ) } } diff --git a/packages/react-sandbox/src/index.ts b/packages/react-sandbox/src/index.ts index 1727568c4..8b31cf681 100644 --- a/packages/react-sandbox/src/index.ts +++ b/packages/react-sandbox/src/index.ts @@ -1,5 +1,5 @@ import React, { useRef, useEffect } from 'react' -import { isFn } from '@designable/shared' +import { isFn, globalThisPolyfill } from '@designable/shared' import { useDesigner, useWorkspace, @@ -44,8 +44,8 @@ export const useSandbox = (props: React.PropsWithChildren) => { ref.current.contentWindow['__DESIGNABLE_LAYOUT__'] = layout ref.current.contentWindow['__DESIGNABLE_ENGINE__'] = designer ref.current.contentWindow['__DESIGNABLE_WORKSPACE__'] = workspace - ref.current.contentWindow['Formily'] = window['Formily'] - ref.current.contentWindow['Designable'] = window['Designable'] + ref.current.contentWindow['Formily'] = globalThisPolyfill['Formily'] + ref.current.contentWindow['Designable'] = globalThisPolyfill['Designable'] ref.current.contentDocument.open() ref.current.contentDocument.write(` @@ -96,15 +96,15 @@ export const useSandbox = (props: React.PropsWithChildren) => { return ref } -if (window.frameElement) { +if (globalThisPolyfill.frameElement) { //解决iframe内嵌如果iframe被移除,内部React无法回收内存的问题 - window.addEventListener('unload', () => { + globalThisPolyfill.addEventListener('unload', () => { ReactDOM.unmountComponentAtNode(document.getElementById('__SANDBOX_ROOT__')) }) } export const useSandboxScope = () => { - return window['__DESIGNABLE_SANDBOX_SCOPE__'] + return globalThisPolyfill['__DESIGNABLE_SANDBOX_SCOPE__'] } export const renderSandboxContent = (render: (scope?: any) => JSX.Element) => { diff --git a/packages/react-settings-form/src/shared/loadScript.ts b/packages/react-settings-form/src/shared/loadScript.ts index f2088d353..17dfaff36 100644 --- a/packages/react-settings-form/src/shared/loadScript.ts +++ b/packages/react-settings-form/src/shared/loadScript.ts @@ -1,4 +1,5 @@ import { getNpmCDNRegistry } from '../registry' +import { globalThisPolyfill } from '@designable/shared' export interface ILoadScriptProps { package: string entry: string @@ -11,7 +12,7 @@ export const loadScript = async (props: ILoadScriptProps) => { base: getNpmCDNRegistry(), ...props, } - if (window[props.root]) return window[options.root] + if (globalThisPolyfill[props.root]) return globalThisPolyfill[options.root] const path = `${options.base}/${options.package}/${options.entry}` return new Promise((resolve, reject) => { const script = document.createElement('script') @@ -19,16 +20,16 @@ export const loadScript = async (props: ILoadScriptProps) => { script.async = false script.src = path script.onload = () => { - const module = window[options.root] - window['define'] = define + const module = globalThisPolyfill[options.root] + globalThisPolyfill['define'] = define resolve(module) script.remove() } script.onerror = (err) => { reject(err) } - const define = window['define'] - window['define'] = undefined + const define = globalThisPolyfill['define'] + globalThisPolyfill['define'] = undefined document.body.appendChild(script) }) } diff --git a/packages/react/src/containers/Viewport.tsx b/packages/react/src/containers/Viewport.tsx index 56f950c3f..ddcc52492 100644 --- a/packages/react/src/containers/Viewport.tsx +++ b/packages/react/src/containers/Viewport.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useRef, useState } from 'react' import { usePrefix, useViewport } from '../hooks' import { AuxToolWidget, EmptyWidget } from '../widgets' import { Viewport as ViewportType } from '@designable/core' -import { requestIdle } from '@designable/shared' +import { requestIdle, globalThisPolyfill } from '@designable/shared' import cls from 'classnames' export interface IViewportProps extends Omit, 'placeholder'> { @@ -36,7 +36,7 @@ export const Viewport: React.FC = ({ }) }) } else { - viewport.onMount(ref.current, window) + viewport.onMount(ref.current, globalThisPolyfill) requestIdle(() => { isFrameRef.current = false setLoaded(true) diff --git a/packages/react/src/hooks/useDesigner.ts b/packages/react/src/hooks/useDesigner.ts index efe03c5c0..3b945da3f 100644 --- a/packages/react/src/hooks/useDesigner.ts +++ b/packages/react/src/hooks/useDesigner.ts @@ -1,14 +1,15 @@ import { useContext, useEffect } from 'react' import { Engine } from '@designable/core' import { DesignerEngineContext } from '../context' -import { isFn } from '@designable/shared' +import { isFn, globalThisPolyfill } from '@designable/shared' export interface IEffects { (engine: Engine): void } export const useDesigner = (effects?: IEffects): Engine => { const designer: Engine = - window['__DESIGNABLE_ENGINE__'] || useContext(DesignerEngineContext) + globalThisPolyfill['__DESIGNABLE_ENGINE__'] || + useContext(DesignerEngineContext) useEffect(() => { if (isFn(effects)) { return effects(designer) diff --git a/packages/react/src/hooks/useLayout.ts b/packages/react/src/hooks/useLayout.ts index 842646b12..f0dad052b 100644 --- a/packages/react/src/hooks/useLayout.ts +++ b/packages/react/src/hooks/useLayout.ts @@ -1,7 +1,11 @@ import { useContext } from 'react' import { DesignerLayoutContext } from '../context' import { IDesignerLayoutContext } from '../types' +import { globalThisPolyfill } from '@designable/shared' export const useLayout = (): IDesignerLayoutContext => { - return window['__DESIGNABLE_LAYOUT__'] || useContext(DesignerLayoutContext) + return ( + globalThisPolyfill['__DESIGNABLE_LAYOUT__'] || + useContext(DesignerLayoutContext) + ) } diff --git a/packages/react/src/hooks/useRegistry.ts b/packages/react/src/hooks/useRegistry.ts index 7166a5d26..dfa17cf94 100644 --- a/packages/react/src/hooks/useRegistry.ts +++ b/packages/react/src/hooks/useRegistry.ts @@ -1,5 +1,6 @@ import { GlobalRegistry, IDesignerRegistry } from '@designable/core' +import { globalThisPolyfill } from '@designable/shared' export const useRegistry = (): IDesignerRegistry => { - return window['__DESIGNER_REGISTRY__'] || GlobalRegistry + return globalThisPolyfill['__DESIGNER_REGISTRY__'] || GlobalRegistry } diff --git a/packages/react/src/hooks/useWorkspace.ts b/packages/react/src/hooks/useWorkspace.ts index 15e2dba61..ab45fd8d4 100644 --- a/packages/react/src/hooks/useWorkspace.ts +++ b/packages/react/src/hooks/useWorkspace.ts @@ -2,13 +2,15 @@ import { useContext } from 'react' import { useDesigner } from './useDesigner' import { WorkspaceContext } from '../context' import { Workspace } from '@designable/core' +import { globalThisPolyfill } from '@designable/shared' + export const useWorkspace = (id?: string): Workspace => { const designer = useDesigner() const workspaceId = id || useContext(WorkspaceContext)?.id if (workspaceId) { return designer.workbench.findWorkspaceById(workspaceId) } - if (window['__DESIGNABLE_WORKSPACE__']) - return window['__DESIGNABLE_WORKSPACE__'] + if (globalThisPolyfill['__DESIGNABLE_WORKSPACE__']) + return globalThisPolyfill['__DESIGNABLE_WORKSPACE__'] return designer.workbench.currentWorkspace } diff --git a/packages/react/src/widgets/OutlineWidget/index.tsx b/packages/react/src/widgets/OutlineWidget/index.tsx index fa374f301..7ed127dc6 100644 --- a/packages/react/src/widgets/OutlineWidget/index.tsx +++ b/packages/react/src/widgets/OutlineWidget/index.tsx @@ -6,6 +6,7 @@ import { OutlineTreeNode } from './OutlineNode' import { Insertion } from './Insertion' import { TreeNode, Viewport } from '@designable/core' import { NodeContext } from './context' +import { globalThisPolyfill } from '@designable/shared' export interface IOutlineTreeWidgetProps { className?: string @@ -31,7 +32,7 @@ export const OutlineTreeWidget: React.FC = observer( outlineRef.current.onUnmount() } if (ref.current && outline) { - outline.onMount(ref.current, window) + outline.onMount(ref.current, globalThisPolyfill) } outlineRef.current = outline return () => { diff --git a/packages/shared/src/coordinate.ts b/packages/shared/src/coordinate.ts index bd7ec4b5d..4695ae31a 100644 --- a/packages/shared/src/coordinate.ts +++ b/packages/shared/src/coordinate.ts @@ -188,7 +188,9 @@ export function calcBoundingRect(rects: IRect[]) { let minLeft = Infinity let maxRight = -Infinity rects.forEach((item) => { - const rect = new DOMRect(item.x, item.y, item.width, item.height) + const rect = + typeof DOMRect !== 'undefined' && + new DOMRect(item.x, item.y, item.width, item.height) if (rect.top <= minTop) { minTop = rect.top } @@ -202,7 +204,10 @@ export function calcBoundingRect(rects: IRect[]) { maxRight = rect.right } }) - return new DOMRect(minLeft, minTop, maxRight - minLeft, maxBottom - minTop) + return ( + typeof DOMRect !== 'undefined' && + new DOMRect(minLeft, minTop, maxRight - minLeft, maxBottom - minTop) + ) } export function calcRectByStartEndPoint( @@ -220,11 +225,14 @@ export function calcRectByStartEndPoint( //4象限 drawStartX = startPoint.x drawStartY = startPoint.y - return new DOMRect( - drawStartX - scrollX, - drawStartY - scrollY, - Math.abs(endPoint.x - startPoint.x + scrollX), - Math.abs(endPoint.y - startPoint.y + scrollY) + return ( + typeof DOMRect !== 'undefined' && + new DOMRect( + drawStartX - scrollX, + drawStartY - scrollY, + Math.abs(endPoint.x - startPoint.x + scrollX), + Math.abs(endPoint.y - startPoint.y + scrollY) + ) ) } else if ( endPoint.x + scrollX < startPoint.x && @@ -233,11 +241,14 @@ export function calcRectByStartEndPoint( //1象限 drawStartX = endPoint.x drawStartY = endPoint.y - return new DOMRect( - drawStartX, - drawStartY, - Math.abs(endPoint.x - startPoint.x) - scrollX, - Math.abs(endPoint.y - startPoint.y) - scrollY + return ( + typeof DOMRect !== 'undefined' && + new DOMRect( + drawStartX, + drawStartY, + Math.abs(endPoint.x - startPoint.x) - scrollX, + Math.abs(endPoint.y - startPoint.y) - scrollY + ) ) } else if ( endPoint.x + scrollX < startPoint.x && @@ -246,21 +257,27 @@ export function calcRectByStartEndPoint( //3象限 drawStartX = endPoint.x drawStartY = startPoint.y - return new DOMRect( - drawStartX - scrollX, - drawStartY - scrollY, - Math.abs(endPoint.x - startPoint.x + scrollX), - Math.abs(endPoint.y - startPoint.y + scrollY) + return ( + typeof DOMRect !== 'undefined' && + new DOMRect( + drawStartX - scrollX, + drawStartY - scrollY, + Math.abs(endPoint.x - startPoint.x + scrollX), + Math.abs(endPoint.y - startPoint.y + scrollY) + ) ) } else { //2象限 drawStartX = startPoint.x drawStartY = endPoint.y - return new DOMRect( - drawStartX, - drawStartY, - Math.abs(endPoint.x - startPoint.x) - scrollX, - Math.abs(endPoint.y - startPoint.y) - scrollY + return ( + typeof DOMRect !== 'undefined' && + new DOMRect( + drawStartX, + drawStartY, + Math.abs(endPoint.x - startPoint.x) - scrollX, + Math.abs(endPoint.y - startPoint.y) - scrollY + ) ) } } diff --git a/packages/shared/src/event.ts b/packages/shared/src/event.ts index 3f3828bc0..55ba76098 100644 --- a/packages/shared/src/event.ts +++ b/packages/shared/src/event.ts @@ -1,5 +1,6 @@ import { isArr, isWindow } from './types' import { Subscribable, ISubscriber } from './subscribable' +import { globalThisPolyfill } from './globalThisPolyfill' const ATTACHED_SYMBOL = Symbol('ATTACHED_SYMBOL') const EVENTS_SYMBOL = Symbol('__EVENTS_SYMBOL__') @@ -106,7 +107,7 @@ export class EventDriver container: EventDriverContainer = document - contentWindow: Window = window + contentWindow: Window = globalThisPolyfill context: Context @@ -323,7 +324,7 @@ export class Event extends Subscribable> { attachEvents( container: EventContainer, - contentWindow: Window = window, + contentWindow: Window = globalThisPolyfill, context?: any ) { if (!container) return diff --git a/packages/shared/src/globalThisPolyfill.ts b/packages/shared/src/globalThisPolyfill.ts new file mode 100644 index 000000000..5c046d753 --- /dev/null +++ b/packages/shared/src/globalThisPolyfill.ts @@ -0,0 +1,19 @@ +function getGlobalThis() { + try { + if (typeof self !== 'undefined') { + return self + } + } catch (e) {} + try { + if (typeof globalThisPolyfill !== 'undefined') { + return globalThisPolyfill + } + } catch (e) {} + try { + if (typeof global !== 'undefined') { + return global + } + } catch (e) {} + return Function('return this')() +} +export const globalThisPolyfill: Window = getGlobalThis() diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index b8ac5db7d..4bc6ddcd6 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -13,3 +13,4 @@ export * from './keycode' export * from './animation' export * from './request-idle' export * from './element' +export * from './globalThisPolyfill' diff --git a/packages/shared/src/instanceof.ts b/packages/shared/src/instanceof.ts index 8dddb090f..db2b36b53 100644 --- a/packages/shared/src/instanceof.ts +++ b/packages/shared/src/instanceof.ts @@ -1,6 +1,10 @@ import { isStr, isFn } from './types' +import { globalThisPolyfill } from './globalThisPolyfill' export const instOf = (value: any, cls: any) => { if (isFn(cls)) return value instanceof cls - if (isStr(cls)) return window[cls] ? value instanceof window[cls] : false + if (isStr(cls)) + return globalThisPolyfill[cls] + ? value instanceof globalThisPolyfill[cls] + : false return false } diff --git a/packages/shared/src/request-idle.ts b/packages/shared/src/request-idle.ts index ec0981c05..e3053db7a 100644 --- a/packages/shared/src/request-idle.ts +++ b/packages/shared/src/request-idle.ts @@ -1,4 +1,5 @@ import 'requestidlecallback' +import { globalThisPolyfill } from './globalThisPolyfill' export interface IIdleDeadline { didTimeout: boolean @@ -13,9 +14,9 @@ export const requestIdle = ( callback: (params: IIdleDeadline) => void, options?: IdleCallbackOptions ): number => { - return window['requestIdleCallback'](callback, options) + return globalThisPolyfill['requestIdleCallback'](callback, options) } export const cancelIdle = (id: number) => { - window['cancelIdleCallback'](id) + globalThisPolyfill['cancelIdleCallback'](id) }