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

Vite+React项目中如何在index.html正确引入外部JS脚本?

在React(Vite)应用中正确引入第三方JS脚本解决元素不存在问题

你在Vite+React项目的index.html中直接插入Cookie弹窗处理脚本时,遇到元素不存在的报错,核心原因是脚本执行时机过早——此时React还未完成组件渲染,#root容器里的.accept-cookie-button、.cookies-policy-banner等DOM元素还未生成,自然找不到目标节点。

以下是几种可行的解决方案:

方法1:将脚本逻辑迁移到React组件中(推荐)

React的设计逻辑更适合通过组件Hook处理DOM交互,把Cookie弹窗的UI和逻辑封装成独立组件,完全融入React生态:

// src/components/CookieBanner.jsx
import { useEffect } from 'react';

export default function CookieBanner() {
  useEffect(() => {
    // 检查已有的Cookie同意状态
    const checkConsentStatus = () => {
      const cookieMatch = document.cookie.match(
        new RegExp("(?:^|; )" + 'cookiesAccepted'.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)")
      );
      if (cookieMatch?.[1] === 'true') {
        document.querySelector('.cookies-policy-banner')?.remove();
      }
    };

    // 处理同意按钮点击事件
    const handleAccept = (e) => {
      e.preventDefault();
      document.cookie = "cookiesAccepted=true;max-age=31536000;path=/";
      document.querySelector('.cookies-policy-banner')?.remove();
    };

    checkConsentStatus();
    const acceptBtn = document.querySelector('.accept-cookie-button');
    acceptBtn?.addEventListener('click', handleAccept);

    // 组件卸载时清理事件监听
    return () => acceptBtn?.removeEventListener('click', handleAccept);
  }, []);

  return (
    <div className="cookies-policy-banner">
      <p>我们使用Cookie优化您的浏览体验</p>
      <button className="accept-cookie-button">接受Cookie</button>
    </div>
  );
}

之后在你的根组件(比如App.jsx)中引入该组件即可,彻底避免DOM不同步问题。

方法2:延迟脚本执行,等待React渲染完成

如果必须在index.html中保留原有脚本,可以通过监听DOMContentLoaded事件+延迟执行,确保React完成初始渲染后再查找DOM元素:

修改index.html中的脚本部分:

<script>
  window.addEventListener('DOMContentLoaded', () => {
    // 延迟100ms确保React完成根组件渲染
    setTimeout(() => {
      const acceptBtn = document.querySelector('.accept-cookie-button');
      const cookieBanner = document.querySelector('.cookies-policy-banner');

      if (acceptBtn && cookieBanner) {
        acceptBtn.addEventListener('click', (event) => {
          event.preventDefault();
          document.cookie = "cookiesAccepted=true;max-age=31536000;path=/";
          cookieBanner.remove();
        });
      }

      const cookieMatch = document.cookie.match(
        new RegExp("(?:^|; )" + 'cookiesAccepted'.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)")
      );
      if (cookieMatch?.[1] === 'true' && cookieBanner) {
        cookieBanner.remove();
      }
    }, 100);
  });
</script>

方法3:用MutationObserver监听DOM变化(适配动态渲染场景)

如果Cookie弹窗是动态渲染(比如根据某些条件显示),可以通过MutationObserver监听#root容器的DOM变化,确保目标元素出现后再绑定事件:

// 在根组件的useEffect中添加
import { useEffect } from 'react';

useEffect(() => {
  const observer = new MutationObserver((mutations) => {
    mutations.forEach(mutation => {
      if (mutation.addedNodes.length) {
        const acceptBtn = document.querySelector('.accept-cookie-button');
        const cookieBanner = document.querySelector('.cookies-policy-banner');
        
        if (acceptBtn && cookieBanner) {
          acceptBtn.addEventListener('click', () => {
            document.cookie = "cookiesAccepted=true;max-age=31536000;path=/";
            cookieBanner.remove();
          });
          observer.disconnect(); // 找到元素后停止监听,避免性能消耗
        }
      }
    });
  });

  observer.observe(document.getElementById('root'), { childList: true, subtree: true });

  return () => observer.disconnect();
}, []);

内容的提问来源于stack exchange,提问作者Alexsander

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 00:54:50