diff --git a/packages/runtime-web/src/api/ui/element-query/intersection-observer.ts b/packages/runtime-web/src/api/ui/element-query/intersection-observer.ts index 3ea2a15a..b06505fd 100644 --- a/packages/runtime-web/src/api/ui/element-query/intersection-observer.ts +++ b/packages/runtime-web/src/api/ui/element-query/intersection-observer.ts @@ -2,6 +2,13 @@ import IO from 'intersection-observer' import { getRootView } from '../../global' import { getDataSet } from './utils' +export interface IntersectionObserverOptions { + thresholds?: any + initialRatio?: number + selectAll?: boolean + dataset?: boolean +} + // 兼容不支持 IntersectionObserver 的浏览器 const IntersectionObserver = window.IntersectionObserver || IO @@ -41,7 +48,7 @@ class LocalIntersectionObserver { initialRatio = 0, selectAll = false, dataset = false - } = {}) { + }: IntersectionObserverOptions = {}) { this.initialRatio = initialRatio this.thresholds = thresholds this.selectAll = selectAll diff --git a/packages/runtime-web/src/runtime/public/component.tsx b/packages/runtime-web/src/runtime/public/component.tsx index a26fc616..6938d917 100644 --- a/packages/runtime-web/src/runtime/public/component.tsx +++ b/packages/runtime-web/src/runtime/public/component.tsx @@ -8,6 +8,7 @@ import ReactDOM from 'react-dom' import eventConvert from './event-convert' import { combineValue, mergeExecution } from './utils/common' import { catchComponentMethodsError } from './utils/errorHandler' +import { mountIntersectionObserver } from './utils/instanceApi' let componetLastId = 0 @@ -206,6 +207,10 @@ export class KBComponent extends React.PureComponent { this.componentConfig.route = window.$getRoute && window.$getRoute() this.componentConfig.pageId = window.$getPageId && window.$getPageId() + this.componentConfig.createIntersectionObserver = (options) => { + return mountIntersectionObserver(options, this.getRoot()) + } + this.updatePageConfig() } @@ -541,7 +546,7 @@ export class KBComponent extends React.PureComponent { // 避免卸载之后继续执行 findDOMNode 操作 if (!this._isMounted) return - const root = ReactDOM.findDOMNode(this) + const root = this.getRoot() if (!root) return for (const nodeId in this.eventsInfo) { @@ -597,4 +602,12 @@ export class KBComponent extends React.PureComponent { registEvents(events, nodeId) { this.eventsInfo[nodeId] = events } + + getRoot() { + try { + return ReactDOM.findDOMNode(this) + } catch (e) { + return null + } + } } diff --git a/packages/runtime-web/src/runtime/public/utils/instanceApi.ts b/packages/runtime-web/src/runtime/public/utils/instanceApi.ts new file mode 100644 index 00000000..994ad7c7 --- /dev/null +++ b/packages/runtime-web/src/runtime/public/utils/instanceApi.ts @@ -0,0 +1,26 @@ +import { my } from '../../../api/my' +import { IntersectionObserverOptions } from '../../../api/ui/element-query/intersection-observer' + +export function mountIntersectionObserver( + options: IntersectionObserverOptions, + root: Element | Text | null +) { + const intersectionObserver = my.createIntersectionObserver(options) + // 保存一份引用,且固定 this 绑定 + const observe = intersectionObserver.observe.bind(intersectionObserver) + + intersectionObserver.observe = (targetSelector, callback) => { + try { + let element = null + if (root && root.parentNode) + element = root.parentNode.querySelector(targetSelector) + // 在这种场景下,查找元素要从当前自定义节点下查找,不能从全局角度查找 + if (element) { + return observe(element, callback) + } + } catch (e) {} + // 处理报错了,或者没有正确的获取到 element 元素,走兜底逻辑,全局查询节点 + return observe(targetSelector, callback) + } + return intersectionObserver +}