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
相关产品推荐
相关产品推荐

