在 react 项目中,完全允许并常见地混合使用原生 javascript(如 dom 操作、事件监听、第三方库初始化等),但需遵循 react 的声明式思维——状态驱动 ui,避免绕过 react 状态直接手动修改 dom,否则可能引发状态不一致和性能问题。
React 本质上是用 JavaScript 编写的 UI 库,它运行在浏览器环境中,因此你写的任何合法 JavaScript(包括 document.querySelector、addEventListener、fetch 等)在技术上都可执行。例如,你提到的 Stacks Design 组件(如 Dropdown、Tooltip)依赖 data-* 属性和 Stacks.js 的全局脚本初始化——这类场景下,在 React 中谨慎集成原生 JS 是合理且可行的。
✅ 推荐做法(安全、可控、符合 React 哲学):
使用 useEffect + useRef 在组件挂载/卸载时初始化/销毁原生交互逻辑,并通过 React 状态(如 useState)同步控制 UI 行为:
import { useState, useEffect, useRef } from 'react
';
function StacksDropdown() {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef(null);
useEffect(() => {
// 初始化 Stacks.js(确保其已加载)
if (window.Stacks && dropdownRef.current) {
// Stacks.js 通常会监听 data-* 属性,但也可主动触发
// 注意:若 Stacks 提供 API,优先调用其方法而非手动 toggle class
const handleToggle = () => setIsOpen(prev => !prev);
dropdownRef.current.addEventListener('click', handleToggle);
return () => {
dropdownRef.current?.removeEventListener('click', handleToggle);
};
}
}, []);
return (
);
}
export default StacksDropdown; ⚠️ 需要避免的做法(反模式):
? 关键原则总结:
简言之:能用 React Hook 解决的交互,就不要绕路写原生 JS;必须用原生 JS 的场景(如集成遗留库、微交互优化),则要严格遵循 React 的生命周期与状态管理规范。 这不是“禁止”,而是“有约束的协同”。