通用监听元素变化 observeElement

// 调用示例
// observeElement('.tooltip.tooltip--memo:not(.fn__none)', ({element, mutationsList, stop})=>{
//     console.log([element?.outerHTML,mutationsList, stop]);
// });
async function observeElement(selector, callback, options, observedEl, delay = 100) {
    let observer, selectorFn = selector;
    let isStopped = false;
    let lastElementExists = false; // 记录上一次元素是否存在
    // 转换选择器为函数
    if (typeof selector !== 'function') {
        selectorFn = () => {
            if (selector?.nodeType === 1) return selector;
            return typeof selector === 'string' ? document.querySelector(selector) : null;
        };
    }
    const stop = () => {
        isStopped = true;
        observer?.disconnect();
    };
    // 初始检查
    const initialElement = selectorFn();
    lastElementExists = !!initialElement;
    if (initialElement && typeof callback === 'function') {
        callback({ element: initialElement, mutationsList: null, stop });
        if (isStopped) return;
    }
    if (isStopped) return;
    // 核心优化:仅在元素存在状态变化时触发回调
    let ticking = false;
    observer = new MutationObserver((mutationsList) => {
        if (!ticking) {
            ticking = true;
            requestAnimationFrame(() => {
                const currentElement = selectorFn();
                const currentExists = !!currentElement;
                // 状态变化时才触发
                if (currentExists !== lastElementExists) {
                    if (currentExists && typeof callback === 'function') {
                        callback({
                            element: currentElement,
                            mutationsList: currentExists ? mutationsList : [],
                            stop
                        });
                    }
                    lastElementExists = currentExists;
                }
                ticking = false;
            });
        }
    });
    if (isStopped) return;
    // 优化监听范围:只监听必要的变化
    if (typeof observedEl === 'string') {
        observedEl = await whenElementExist(observedEl);
        if (isStopped) return;
    }
    observer.observe(observedEl || document.body, options || {childList: true, subtree: true});
}

image.png

留下你的脚步
推荐阅读