diff --git a/packages/core/src/models/MoveHelper.ts b/packages/core/src/models/MoveHelper.ts index a3738264b..da4a0fd75 100644 --- a/packages/core/src/models/MoveHelper.ts +++ b/packages/core/src/models/MoveHelper.ts @@ -80,6 +80,10 @@ export class MoveHelper { this.makeObservable() } + get cursor() { + return this.operation.engine.cursor + } + get viewport() { return this.operation.workspace.viewport } @@ -274,7 +278,8 @@ export class MoveHelper { source: this.dragNodes, }) ) - this.operation.engine.cursor.setDragType(CursorDragType.Move) + this.viewport.cacheElements() + this.cursor.setDragType(CursorDragType.Move) this.dragging = true } } @@ -349,6 +354,7 @@ export class MoveHelper { this.viewportClosestDirection = null this.viewportClosestOffsetRect = null this.viewportClosestRect = null + this.viewport.clearCache() } trigger(event: any) { diff --git a/packages/core/src/models/NodeSelector.ts b/packages/core/src/models/NodeSelector.ts deleted file mode 100644 index 8a5e5de42..000000000 --- a/packages/core/src/models/NodeSelector.ts +++ /dev/null @@ -1,52 +0,0 @@ -export type SelectorStore = Map< - string, //id - WeakMap -> - -export class NodeSelector { - private store: SelectorStore = new Map() - - private _queryAll(target: HTMLElement, attrName: string, id: string) { - if (!target) return [] - target - .querySelectorAll(`*[${attrName}]`) - .forEach((element: HTMLElement) => { - const _id = element.getAttribute(attrName) - const map = this.store.get(_id) - if (map) { - const elements = map.get(target) - if (!elements) { - map.set(target, [element]) - } else { - map.set(target, elements.concat(element)) - } - } else { - this.store.set(_id, new WeakMap([[target, [element]]])) - } - }) - return this.store.get(id)?.get(target) ?? [] - } - - private _clean(target: HTMLElement, id: string) { - const caches = this.store.get(id) - if (caches) { - caches.delete(target) - } - } - - queryAll(target: HTMLElement, attrName: string, id: string): HTMLElement[] { - const caches = this.store.get(id) - if (caches) { - const elements = caches.get(target) - if (!elements || elements.some((el) => !el.isConnected)) - return this._queryAll(target, attrName, id) - return elements - } else { - return this._queryAll(target, attrName, id) - } - } - - query(target: HTMLElement, attrName: string, id: string) { - return this.queryAll(target, attrName, id)?.[0] - } -} diff --git a/packages/core/src/models/Viewport.ts b/packages/core/src/models/Viewport.ts index 6a6c7d5cb..7003c0a4a 100644 --- a/packages/core/src/models/Viewport.ts +++ b/packages/core/src/models/Viewport.ts @@ -15,7 +15,6 @@ import { action, define, observable } from '@formily/reactive' import { Workspace } from './Workspace' import { Engine } from './Engine' import { TreeNode } from './TreeNode' -import { NodeSelector } from './NodeSelector' export interface IViewportProps { engine: Engine @@ -42,8 +41,6 @@ export type IViewportMoveInsertionType = 'all' | 'inline' | 'block' export class Viewport { workspace: Workspace - selector: NodeSelector - engine: Engine contentWindow: Window @@ -70,6 +67,8 @@ export class Viewport { moveInsertionType: IViewportMoveInsertionType + nodeElementsStore: Record = {} + constructor(props: IViewportProps) { this.workspace = props.workspace this.engine = props.engine @@ -78,7 +77,6 @@ export class Viewport { this.viewportElement = props.viewportElement this.contentWindow = props.contentWindow this.nodeIdAttrName = props.nodeIdAttrName - this.selector = new NodeSelector() this.digestViewport() this.makeObservable() this.attachEvents() @@ -178,6 +176,21 @@ export class Viewport { return this.scrollY - this.dragStartSnapshot.scrollY } + cacheElements() { + this.nodeElementsStore = {} + this.viewportRoot + ?.querySelectorAll(`*[${this.nodeIdAttrName}]`) + .forEach((element: HTMLElement) => { + const id = element.getAttribute(this.nodeIdAttrName) + this.nodeElementsStore[id] = this.nodeElementsStore[id] || [] + this.nodeElementsStore[id].push(element) + }) + } + + clearCache() { + this.nodeElementsStore = {} + } + getCurrentData() { const data: IViewportData = {} if (this.isIframe) { @@ -305,14 +318,22 @@ export class Viewport { }) } - findElementById(id: string) { + findElementById(id: string): HTMLElement { if (!id) return - return this.selector.query(this.viewportRoot, this.nodeIdAttrName, id) + if (this.nodeElementsStore[id]) return this.nodeElementsStore[id][0] + return this.viewportRoot?.querySelector( + `*[${this.nodeIdAttrName}='${id}']` + ) as HTMLElement } - findElementsById(id: string) { + findElementsById(id: string): HTMLElement[] { if (!id) return [] - return this.selector.queryAll(this.viewportRoot, this.nodeIdAttrName, id) + if (this.nodeElementsStore[id]) return this.nodeElementsStore[id] + return Array.from( + this.viewportRoot?.querySelectorAll( + `*[${this.nodeIdAttrName}='${id}']` + ) ?? [] + ) } containsElement(element: HTMLElement | Element | EventTarget) { diff --git a/packages/shared/src/element.ts b/packages/shared/src/element.ts index df5907693..03f849e6a 100644 --- a/packages/shared/src/element.ts +++ b/packages/shared/src/element.ts @@ -75,6 +75,7 @@ export const calcElementOuterWidth = ( export const calcElementLayout = (element: Element) => { if (!element) return 'vertical' const parent = element.parentElement + if (!parent) return 'vertical' const tagName = element.tagName const parentTagName = parent.tagName const style = getComputedStyle(element)