繁体   English   中英

ReactJS - 使用 Mutation Observer 检测第三方 DOM 插入

[英]ReactJS - Detect third-party DOM insert using Mutation Observer

在组件内部,第三方 JavaScript 库在 React 渲染后将一些内容注入到特定的 DIV( voice-service )中。 当使用 Mutation Observer 注入 DOM 时,我想在该 DIV( voice-service )上添加或删除一些 CSS 类,例如 -

当 DOM 注入时 -

<div id="maxVoiceContainer" class="voice-service service--active">
 // third-party content
</div>

当 DOM 未注入时 -

<div id="maxVoiceContainer" class="voice-service service--inactive">
// third-party content
</div>

英雄语音组件:

import React, { useRef, useState, useEffect } from 'react';

const heroVoice = (props) => {

    const elementRef = useRef();
    const [voiceAvailability, setVoiceAvailability] = useState(false);

    useEffect(() => {
        const config = { attributes: false, characterData: false, childList: true, subtree: true, attributeOldValue: false, characterDataOldValue: false };
        const observer = new MutationObserver(mutations => {
            mutations.forEach(mutation => {
                const newNodes = mutation.addedNodes;
                newNodes.forEach(node => {
                    if (node.classList && node.classList.contains('pocket-sphinx-container')) {
                        setVoiceAvailability(status => !status);
                    }
                });
            });
        });
        observer.observe(elementRef.current, config);
    }, []);

    return (
        <div
            ref={elementRef}
            id="maxVoiceContainer"
            className={`voice-service ${voiceAvailability ? ' service--active' : 'service--inactive'}`}
        >
          // third-party content
        </div>
    );
}

export default heroVoice;

想知道 -

  1. 我需要断开观察者的连接吗?
  2. 看起来不错? 最佳实践?
  3. 另外,我不想在状态更新时重新渲染!

问:我需要断开观察者的连接吗? 它不是直接需要的,但我推荐使用mutationObserver.disconnect()方法,因为你在 ComponentDidMount 上被调用一次。 第二个参数处的空数组表示它。 参考

看起来不错? 最佳实践? 是的,看起来不错。 避免嵌套 forEach。 最好先使用地图而不是 forEach

 mutations.map(mutation => mutation.addedNodes).forEach(node => { if (node.classList && node.classList.contains('pocket-sphinx-container')) { setVoiceAvailability(status => !status); } });

另外,我不想在状态更新时重新渲染! React 的生命周期就是为此而构建的。 有两种可能。 首先,您可以使用 Redux 或创建一个在 forEach 中设置的局部变量。 但一般不要在 forEach 中使用 setState 钩子

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM