监听 HTMLCollection 的变化(或实现类似的效果)

问题描述 投票:0回答:1

我需要创建一个简单的工具提示库,其工作原理如下:

每个具有特定属性组合的 DOM 元素(例如 class="tooltip"、data-tooltip-text="some text")都会在悬停时自动显示工具提示(包含来自数据属性的文本)。

此行为必须通过外部 DOM 操作持续存在。我真的很喜欢为此利用 HTMLcollection 的想法,因为它的“实时”性质,因为每次 DOM 更改时迭代整个 DOM 听起来可能非常困难。

现在我很想观看/收听该集合,并在每次更改时运行一个序列(遍历节点,查看它们是否有侦听器,如果没有则添加它)。

我该怎么做? watchobserve 方法似乎(如果我理解正确的话)能够做到这一点,但它们现在已被弃用。 MDN 说 Proxy 涵盖了大多数用例,但它是否涵盖了我的用例(我还没有找到使其工作的方法)?或者我还缺少其他什么方式吗?

那么MutationObserver呢?我认为深入观察整个应用程序并在每次更改时通过 querySelectorAll 重复获取新的 NodeList 要求太高(该库应该在 React 应用程序上运行)。通过 React 将 HTMLCollection(作为值)动态提交到 DOM 中,然后(浅层)使用 MutationObserver 监听更改可能会起作用,但我怀疑这是否是一个好主意。

javascript performance tooltip watch mutation-observers
1个回答
0
投票

我对此不太确定,因为我不太擅长 React,但我认为这应该适合您的场景:

class Tooltip {
    constructor() {
        this.initTooltips();
        this.observeDOMChanges();
    }

    initTooltips() {
        const elements = document.querySelectorAll('[class="tooltip"][data-tooltip-text]');
        elements.forEach(element => {
            if (!element.dataset.tooltipInitialized) {
                this.addTooltipListener(element);
                element.dataset.tooltipInitialized = true;
            }
        });
    }

    addTooltipListener(element) {
        const tooltipText = element.getAttribute('data-tooltip-text');
        const tooltip = document.createElement('div');
        tooltip.className = 'tooltip-content';
        tooltip.innerText = tooltipText;
        document.body.appendChild(tooltip);

        element.addEventListener('mouseenter', () => {
            tooltip.style.display = 'block';
            const rect = element.getBoundingClientRect();
            tooltip.style.left = `${rect.left + window.scrollX}px`;
            tooltip.style.top = `${rect.bottom + window.scrollY}px`;
        });

        element.addEventListener('mouseleave', () => {
            tooltip.style.display = 'none';
        });

        // If you want you can remove the tooltip when it's removed from the DOM
        element.addEventListener('DOMNodeRemoved', () => {
            tooltip.remove();
        });
    }

    observeDOMChanges() {
        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                if (mutation.type === 'childList') {
                    this.initTooltips(); // Reinitialize tooltips when child elements change
                }
            });
        });

        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }
}


const tooltipLibrary = new Tooltip();

我不太确定

Proxy
是如何工作的,但我相信使用
Proxy
进行 DOM 观察有点不传统。我希望这能解决您的问题。

© www.soinside.com 2019 - 2024. All rights reserved.