You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS根据div class判断遮罩状态新增DOM元素条件失效问题

实现目标

基于「页面遮罩层处于隐藏状态」的判断条件,满足条件时向DOM中新增指定元素。

遮罩层参考HTML结构

<div id="mobile-start-container" class="fn-npnxnanbnsnfns01001000001" style="display: none;">
    <div class="mobile-start-overlay shown" role="dialog" aria-modal="true" aria-labelledby="mobile-start-title" data-reactid=".0">
        <div class="mobile-load-title-overlay" style="opacity:0;" data-reactid=".0.0">
            <div class="mobile-load-title" id="mobile-start-title" data-reactid=".0.0.0">FORMATION AU PROGRAMME PRIMAIRE</div>
        </div>
        <div data-reactid=".0.4">
            <div class="mobile-start-resume-text" data-reactid=".0.4.0"><button aria-label="Reprendre" tabindex="0" style="font-size:100%;border-radius:30px;" data-reactid=".0.4.0.0">Reprendre</button></div>
            <button class="restart" aria-label="Redémarrer" tabindex="0" data-reactid=".0.4.1">
                <svg class="cs-icon" preserveAspectRatio="none" x="0px" y="0px" width="13px" height="15.75px" focusable="false" tabindex="-1" data-reactid=".0.4.1.0">
                    <path fill="#FFFFFF" transform="scale(1, 1) translate(0, 0)" stroke="none" d=" M 10.95 8.75 Q 11 9 11 9.25 10.95 11.15 9.7 12.4 8.4 13.7 6.5 13.75 4.6 13.7 3.3 12.4 2.05 11.15 2 9.25 2.05 7.3 3.3 6.05 4.398828125 4.998828125 6 4.75 L 6 6.9 Q 6.05 7.75 6.85 7.35 L 11.35 4.3 Q 11.7 4.05 11.7 3.75 11.7 3.45 11.35 3.2 L 6.85 0.15 Q 6.05 -0.3 6 0.6 L 6 2.75 Q 3.4517578125 3.001171875 1.8 4.75 0.05 6.6 0 9.25 0.05 12 1.9 13.85 3.75 15.65 6.5 15.75 9.25 15.65 11.1 13.85 12.95 12 13 9.25 13 9 13 8.75 L 10.95 8.75 Z" data-reactid=".0.4.1.0.0"></path>
                </svg>
                <div class="restart-text" style="color:white;display:inline-block;padding-left:1em;transform:translateY(-3px);font-size:13px;" data-reactid=".0.4.1.1">Redémarrer</div>
            </button>
        </div>
        <div class="mobile-start-course-title" style="font-size: 20.28px;" data-reactid=".0.5">FORMATION AU PROGRAMME PRIMAIRE</div>
    </div>
</div>

原有问题脚本

document.body.onload = addElement;

function addElement() {
    var overlayContainer = document.getElementById("mobile-start-container");
    console.log(overlayContainer);
    var divOverlay = document.getElementsByClassName("mobile-start-overlay")[0];
    console.log(divOverlay);

    if (divOverlay.classList.contains('shown')) {
        console.log("overlay is shown so don't display the button");

    } else {

        // Create new Button element
        var newButton = document.createElement("button");
        // add class to the new Button
        newButton.className = "question-btn";
        // add SVG tag inside Button
        var newSvg = document.createElement("svg");
        // add class to svg tag
        newSvg.className = "svg-icon";
        // fill svg element with my shape
        var svgContent = document.createElementNS("http://www.w3.org/2000/svg", 'path');
        svgContent.setAttribute("d", "M 0 0 L 10 10");
        svgContent.style.stroke = "#fff";
        svgContent.style.strokeWidth = "1px";
        newSvg.appendChild(svgContent);
        // add svg node to created button
        newButton.appendChild(newSvg);
        // add new button somewhere else in DOM
        var currentDiv = document.getElementById('nav-controls');
        document.body.insertBefore(newButton, currentDiv);

        console.log(newButton);

    }
}

现存问题

  • 核心故障:条件判断逻辑不生效,无论遮罩层是显示(包含shown类)还是隐藏状态,新增按钮都会始终被渲染
  • 次要问题:svg标签内的path无法正常显示(暂不优先处理)
故障原因
  1. 触发时机错误:遮罩层由React渲染,body.onload触发时React可能还未完成组件挂载,仅在页面加载完成时做一次判断,无法捕获后续遮罩层显隐切换时的类名、样式变化,导致判断结果和实际状态不一致。
  2. 判断维度不全:仅校验了内层.mobile-start-overlay的shown类,未校验外层容器#mobile-start-container的display: none样式,而外层容器的行内样式才是控制遮罩整体显隐的关键属性。
  3. SVG创建API错误:创建SVG元素必须使用带SVG命名空间的createElementNS方法,原有代码中用createElement创建svg标签,会导致浏览器将其识别为普通HTML元素,内部path无法正常渲染。
  4. 缺少重复渲染校验:没有判断按钮是否已经存在于DOM中,逻辑触发时会重复插入元素。
修复后代码
// 初始化标记,避免重复绑定监听
let hasInitOverlayWatch = false;

function handleOverlayStatusChange() {
  const overlayContainer = document.getElementById("mobile-start-container");
  const divOverlay = document.querySelector(".mobile-start-overlay");
  const existBtn = document.querySelector(".question-btn");
  const navContainer = document.getElementById('nav-controls');
  // 必要DOM未挂载时直接跳过本次判断
  if (!overlayContainer || !divOverlay || !navContainer) return;

  // 遮罩显示判定规则:外层容器未设置display:none + 内层遮罩带shown类
  const isOverlayShown = !overlayContainer.style.display.includes('none') && divOverlay.classList.contains('shown');

  if (isOverlayShown) {
    // 遮罩显示时移除已插入的按钮
    if (existBtn) existBtn.remove();
    console.log("overlay is shown so don't display the button");
  } else {
    // 遮罩隐藏时,按钮不存在才插入,避免重复渲染
    if (!existBtn) {
      // 创建按钮
      const newButton = document.createElement("button");
      newButton.className = "question-btn";

      // 修复SVG渲染问题:所有SVG相关元素统一使用SVG命名空间创建
      const svgNS = "http://www.w3.org/2000/svg";
      const newSvg = document.createElementNS(svgNS, "svg");
      newSvg.setAttribute('width', '16');
      newSvg.setAttribute('height', '16');
      newSvg.setAttribute('viewBox', '0 0 10 10');
      newSvg.className = "svg-icon";

      const svgContent = document.createElementNS(svgNS, 'path');
      svgContent.setAttribute("d", "M 0 0 L 10 10");
      svgContent.style.stroke = "#fff";
      svgContent.style.strokeWidth = "1px";
      newSvg.appendChild(svgContent);

      newButton.appendChild(newSvg);
      // 插入到指定DOM位置
      document.body.insertBefore(newButton, navContainer);
      console.log("insert button success", newButton);
    }
  }
}

function initOverlayWatch() {
  if (hasInitOverlayWatch) return;
  hasInitOverlayWatch = true;

  // 初始化时先执行一次状态判断
  handleOverlayStatusChange();

  // 监听DOM属性变化,适配React异步渲染、遮罩动态切换的场景
  const observer = new MutationObserver(() => {
    handleOverlayStatusChange();
  });

  observer.observe(document.body, {
    attributes: true,
    subtree: true,
    // 只监听类名、样式变化,减少性能消耗
    attributeFilter: ['class', 'style']
  });
}

// 兼容不同页面加载状态,初始化监听
if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initOverlayWatch);
} else {
  initOverlayWatch();
}

内容的提问来源于stack exchange,提问作者G. Delvigne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 19:48:28